Spec-Zone.ru › OpenJDK 8

Интерфейс Instrumentation


public interface Instrumentation

Этот класс предоставляет службы, необходимые для инструментирования кода языка программирования Java. Инструментирование — это добавление байткодов к методам для сбора данных, которые будут использоваться инструментами. Поскольку изменения носят чисто аддитивный характер, эти инструменты не изменяют состояние или поведение приложения. Примеры таких безвредных инструментов включают агенты мониторинга, профайлеры, анализаторы покрытия и логирующие события.

Существует два способа получения экземпляра интерфейса Instrumentation:

  1. Когда JVM запускается таким образом, что указывает на класс агента. В этом случае экземпляр Instrumentation передаётся методу premain класса агента.

  2. Когда JVM предоставляет механизм для запуска агентов в какой-то момент после запуска JVM. В этом случае экземпляр Instrumentation передаётся методу agentmain кода агента.

Эти механизмы описаны в спецификации пакета.

После того, как агент получит экземпляр Instrumentation, агент может вызывать методы экземпляра в любое время.

Since:
1.5

Методы

Модификатор и тип Метод и описание
void addTransformer(ClassFileTransformer transformer)

Регистрирует предоставленный трансформатор.

void addTransformer(ClassFileTransformer transformer, boolean canRetransform)

Регистрирует предоставленный трансформатор.

void appendToBootstrapClassLoaderSearch(JarFile jarfile)

Указывает JAR-файл с классами инструментирования, которые должны быть определены загрузчиком базовых классов.

void appendToSystemClassLoaderSearch(JarFile jarfile)

Указывает JAR-файл с классами инструментирования, которые должны быть определены системным загрузчиком классов.

Class[] getAllLoadedClasses()

Возвращает массив всех классов, в настоящее время загруженных JVM.

Class[] getInitiatedClasses(ClassLoader loader)

Возвращает массив всех классов, для которых loader является инициализирующим загрузчиком.

long getObjectSize(Object objectToSize)

Возвращает зависящее от реализации приближенное значение объема памяти, занимаемого указанным объектом.

boolean isModifiableClass(Class<?> theClass)

Определяет, может ли класс быть изменён с помощью перетрансформации или переопределения.

boolean isNativeMethodPrefixSupported()

Возвращает, поддерживает ли текущая конфигурация JVM установку префикса для методов нативного кода.

boolean isRedefineClassesSupported()

Возвращает, поддерживает ли текущая конфигурация JVM переопределение классов.

boolean isRetransformClassesSupported()

Возвращает, поддерживает ли текущая конфигурация JVM перетрансформацию классов.

void redefineClasses(ClassDefinition... definitions)

Переопределяет указанный набор классов с использованием предоставленных файлов классов.

boolean removeTransformer(ClassFileTransformer transformer)

Отменяет регистрацию предоставленного трансформатора.

void retransformClasses(Class<?>... classes)

Перетрансформирует указанный набор классов.

void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix)

Этот метод изменяет обработку ошибок при разрешении методов нативного кода, позволяя повторную попытку с применением префикса к имени.

Методы

addTransformer

void addTransformer(ClassFileTransformer transformer,
                    boolean canRetransform)

Регистрирует предоставленный трансформер. Все будущие определения классов будут видны трансформеру, за исключением определений классов, от которых зависит любой зарегистрированный трансформер. Трансформер вызывается при загрузке классов, при их переопределении и, если canRetransform имеет значение true, при их повторном преобразовании. См. ClassFileTransformer.transform для порядка вызовов преобразования. Если трансформер генерирует исключение во время выполнения, JVM всё равно вызовет другие зарегистрированные трансформеры в порядке. Один и тот же трансформер можно добавить более одного раза, но это крайне не рекомендуется — избегайте этого, создав новый экземпляр класса трансформера.

Этот метод предназначен для использования в инструментировании, как описано в спецификации класса.

Параметры:
transformer - трансформер для регистрации
canRetransform - могут ли преобразования этого трансформера быть повторно преобразованы
Исключения:
NullPointerException - если передан null трансформер
UnsupportedOperationException - если canRetransform равно true, и текущая конфигурация JVM не позволяет повторного преобразования (isRetransformClassesSupported() равно false)
С:
1.6

addTransformer

void addTransformer(ClassFileTransformer transformer)

Регистрирует предоставленный трансформер.

То же самое, что и addTransformer(transformer, false).

Параметры:
transformer - трансформер для регистрации
Исключения:
NullPointerException - если передан null трансформер
См. также:
addTransformer(ClassFileTransformer,boolean)

removeTransformer

boolean removeTransformer(ClassFileTransformer transformer)

Дерегистрирует предоставленный трансформер. Будущие определения классов не будут отображаться трансформеру. Удаляет последний добавленный соответствующий экземпляр трансформера. Из-за многопоточного характера загрузки классов, трансформер может получать вызовы после того, как он был удален. Трансформеры должны быть написаны таким образом, чтобы ожидать эту ситуацию.

Параметры:
transformer - трансформер для отмены регистрации
Возвращает:
true, если трансформер был найден и удален, false, если трансформер не был найден
Исключения:
NullPointerException - если передан null трансформер

isRetransformClassesSupported

boolean isRetransformClassesSupported()

Возвращает значение, указывающее, поддерживает ли текущая конфигурация JVM повторное преобразование классов. Возможность повторного преобразования уже загруженного класса — это необязательная возможность JVM. Повторное преобразование будет поддерживаться только в том случае, если атрибут manifest Can-Retransform-Classes установлено в значение true в файле JAR агента (как описано в спецификации пакета), и JVM поддерживает эту возможность. Во время одной инстанциации одной JVM несколько вызовов этого метода всегда возвращают один и тот же ответ.

Возвращает:
true, если текущая конфигурация JVM поддерживает повторное преобразование классов, false — если нет.
С:
1.6
См. также:
retransformClasses(java.lang.Class<?>...)

retransformClasses

void retransformClasses(Class<?>... classes)
                 throws UnmodifiableClassException

Повторно преобразует указанный набор классов.

Эта функция упрощает инструментирование уже загруженных классов. При первоначальной загрузке классов или при их переопределении начальные байты файла класса можно преобразовать с помощью ClassFileTransformer. Эта функция повторно запускает процесс преобразования (вне зависимости от того, производилось ли преобразование ранее). Это повторное преобразование выполняется в следующей последовательности:

  • начиная с начальных байтов файла класса
  • для каждого трансформера, который был добавлен с canRetransform равным false, байты, возвращённые методом transform во время последней загрузки или переопределения класса, используются в качестве результата преобразования; обратите внимание, что это эквивалентно повторному применению предыдущего преобразования без изменений; за исключением того, что transform не вызывается
  • для каждого трансформера, который был добавлен с canRetransform равным true, вызывается метод transform в этих трансформерах
  • преобразованные байты файла класса устанавливаются в качестве нового определения класса

Порядок преобразования описан в методе transform. Этот же порядок используется при автоматическом повторном применении преобразований, не способных к повторному преобразованию.

Начальные байты файла класса представляют байты, переданные методу ClassLoader.defineClass или redefineClasses (до применения каких-либо преобразований), но они могут не совпадать с ними полностью. Пул констант может иметь другую структуру или содержимое. Пул констант может содержать больше или меньше элементов. Элементы пула констант могут быть в другом порядке; однако, индексы пула констант в байкодах методов будут соответствовать. Некоторые атрибуты могут отсутствовать. В тех случаях, когда порядок не имеет значения, например, порядок методов, он может не сохраняться.

Этот метод работает с набором, чтобы разрешить взаимозависимые изменения более чем одного класса одновременно (повторное преобразование класса A может потребовать повторного преобразования класса B).

Если у переобразованного метода есть активные стековые фреймы, эти активные фреймы продолжают выполнять байткоды оригинального метода. Переобразованный метод будет использоваться при новых вызовах.

Этот метод не вызывает никакой инициализации, кроме той, что происходит в соответствии с обычными семантиками JVM. Другими словами, переопределение класса не приводит к запуску его инициализаторов. Значения статических переменных останутся такими же, как и до вызова.

Экземпляры переобразованного класса не затрагиваются.

Повторное преобразование может изменить тела методов, пул констант и атрибуты. Повторное преобразование не должно добавлять, удалять или переименовывать поля или методы, изменять сигнатуры методов или изменять наследование. Эти ограничения могут быть сняты в будущих версиях. Байты файла класса не проверяются, не верифицируются и не устанавливаются до тех пор, пока не будут применены преобразования. Если полученные байты содержат ошибку, этот метод сгенерирует исключение.

Если этот метод сгенерирует исключение, то ни один класс не был переобразован.

Этот метод предназначен для использования в инструментировании, как описано в спецификации класса.

Параметры:
classes - массив классов для повторного преобразования; разрешается массив нулевой длины, в этом случае этот метод ничего не делает
Исключения:
UnmodifiableClassException - если указанный класс не может быть изменён (isModifiableClass(java.lang.Class<?>) вернул бы false)
UnsupportedOperationException - если текущая конфигурация JVM не позволяет повторного преобразования (isRetransformClassesSupported() равно false) или повторное преобразование пыталось выполнить недопустимые изменения
ClassFormatError - если данные не содержат допустимого класса
NoClassDefFoundError - если имя в файле класса не равно имени класса
UnsupportedClassVersionError - если номера версий файла класса не поддерживаются
ClassCircularityError - если новые классы содержат цикличность
LinkageError - если произошла ошибка связи
NullPointerException - если массив классов, переданный в качестве аргумента, или любой его компонент null.
С:
1.6
См. также:
isRetransformClassesSupported(), addTransformer(java.lang.instrument.ClassFileTransformer, boolean), ClassFileTransformer

isRedefineClassesSupported

boolean isRedefineClassesSupported()

Возвращает значение, указывающее, поддерживает ли текущая конфигурация JVM переопределение классов. Возможность переопределения уже загруженного класса — это необязательная возможность JVM. Переопределение будет поддерживаться только в том случае, если атрибут manifest Can-Redefine-Classes установлен в значение true в файле JAR агента (как описано в спецификации пакета), и JVM поддерживает эту возможность. Во время одной инстанциации одной JVM несколько вызовов этого метода всегда возвращают один и тот же ответ.

Возвращает:
true, если текущая конфигурация JVM поддерживает переопределение классов, false — если нет.
См. также:
redefineClasses(java.lang.instrument.ClassDefinition...)

redefineClasses

void redefineClasses(ClassDefinition... definitions)
              throws ClassNotFoundException,
                     UnmodifiableClassException

Переопределите предоставленный набор классов, используя предоставленные файлы классов.

Этот метод используется для замены определения класса без ссылки на байты существующего файла класса, как это можно сделать при повторной компиляции из исходного кода для отладки с исправлением и продолжением. В тех случаях, когда существующие байты файла класса должны быть преобразованы (например, при инструментировании байткода) retransformClasses следует использовать.

Этот метод работает с набором, чтобы позволить одновременные взаимозависимые изменения для более чем одного класса (переопределение класса A может потребовать переопределения класса B).

Если переопределённый метод имеет активные стековые фреймы, эти активные фреймы продолжают выполнять байткод исходного метода. Переопределённый метод будет использоваться при новых вызовах.

Этот метод не вызывает никакой инициализации, кроме той, которая произошла бы в соответствии с обычными семантиками JVM. Другими словами, переопределение класса не приводит к выполнению его инициализаторов. Значения статических переменных останутся такими, какими они были до вызова.

Экземпляры переопределённого класса не затрагиваются.

Переопределение может изменить тела методов, пул констант и атрибуты. Переопределение не должно добавлять, удалять или переименовывать поля или методы, изменять сигнатуры методов или изменять наследование. Эти ограничения могут быть сняты в будущих версиях. Байты файла класса не проверяются, не верифицируются и не устанавливаются до тех пор, пока не будут применены все преобразования. Если результирующие байты содержат ошибки, этот метод выбросит исключение.

Если этот метод выбросит исключение, ни один класс не был переопределён.

Этот метод предназначен для использования в инструментировании, как описано в спецификации класса.

Параметры:
definitions - массив классов для переопределения с соответствующими определениями; разрешён массив нулевой длины, в этом случае метод ничего не делает
Исключения:
UnmodifiableClassException - если указанный класс не может быть изменён (isModifiableClass(java.lang.Class<?>) вернёт false)
UnsupportedOperationException - если текущая конфигурация JVM не позволяет переопределение (isRedefineClassesSupported() ложно) или переопределение попыталось выполнить неподдерживаемые изменения
ClassFormatError - если данные не содержат допустимого класса
NoClassDefFoundError - если имя в файле класса не равно имени класса
UnsupportedClassVersionError - если номера версий файла класса не поддерживаются
ClassCircularityError - если новые классы содержат цикличность
LinkageError - если возникает ошибка связи
NullPointerException - если предоставленный массив определений или любой из его компонентов null
ClassNotFoundException - Не может быть выброшен (присутствует только для совместимости)
См. также:
isRedefineClassesSupported(), addTransformer(java.lang.instrument.ClassFileTransformer, boolean), ClassFileTransformer

isModifiableClass

boolean isModifiableClass(Class<?> theClass)

Определяет, может ли класс быть изменён с помощью перетрансформации или переопределения. Если класс изменяемый, этот метод возвращает true. Если класс не изменяемый, этот метод возвращает false.

Для перетрансформации класса, isRetransformClassesSupported() также должно быть истинным. Но значение isRetransformClassesSupported() не влияет на значение, возвращаемое этой функцией. Для переопределения класса, isRedefineClassesSupported() также должно быть истинным. Но значение isRedefineClassesSupported() не влияет на значение, возвращаемое этой функцией.

Примитивные классы (например, java.lang.Integer.TYPE) и массивы никогда не изменяемы.

Параметры:
theClass - класс, который нужно проверить на возможность изменения
Возвращает:
можно ли изменить указанный класс
Исключения:
NullPointerException - если указанный класс null.
С момента:
1.6
См. также:
retransformClasses(java.lang.Class<?>...), isRetransformClassesSupported(), redefineClasses(java.lang.instrument.ClassDefinition...), isRedefineClassesSupported()

getAllLoadedClasses

Class[] getAllLoadedClasses()

Возвращает массив всех классов, загруженных в данный момент JVM.

Возвращает:
массив, содержащий все классы, загруженные JVM, нулевой длины, если их нет

getInitiatedClasses

Class[] getInitiatedClasses(ClassLoader loader)

Возвращает массив всех классов, для которых loader является инициализирующим загрузчиком. Если предоставленный загрузчик null, возвращаются классы, инициализированные загрузчиком Bootstrap.

Параметры:
loader - загрузчик, чьи инициализированные классы будут возвращены
Возвращает:
массив, содержащий все классы, для которых загрузчик является инициализирующим загрузчиком, нулевой длины, если их нет

getObjectSize

long getObjectSize(Object objectToSize)

Возвращает специфичную для реализации приблизительную оценку объёма памяти, занимаемой указанным объектом. Результат может включать часть или все накладные расходы объекта, и, таким образом, полезен для сравнения в рамках одной реализации, но не между реализациями. Оценка может меняться во время одного вызова JVM.

Параметры:
objectToSize - объект, для которого требуется оценка размера
Возвращает:
специфичная для реализации приблизительная оценка объёма памяти, занимаемой указанным объектом
Исключения:
NullPointerException - если предоставленный объект null.

appendToBootstrapClassLoaderSearch

void appendToBootstrapClassLoaderSearch(JarFile jarfile)

Указывает файл JAR с классами инструментирования, которые должны быть определены загрузчиком Bootstrap.

Когда встроенный загрузчик класса виртуальной машины, известный как "загрузчик Bootstrap", неуспешно ищет класс, записи в JAR file также будут просмотрены.

Этот метод можно использовать несколько раз для добавления нескольких файлов JAR для поиска в порядке вызова этого метода.

Агент должен позаботиться о том, чтобы JAR-файл не содержал никаких классов или ресурсов, кроме тех, которые должны быть определены загрузчиком Bootstrap в целях инструментирования. Несоблюдение этого предупреждения может привести к неожиданному поведению, которое трудно диагностировать. Например, предположим, что есть загрузчик L, а родитель L для делегирования — загрузчик Bootstrap. Кроме того, метод в классе C, определённом L, ссылается на закрытый вспомогательный класс C$1. Если JAR-файл содержит класс C$1, то делегирование загрузчику Bootstrap приведёт к определению C$1 загрузчиком Bootstrap. В этом примере будет брошено IllegalAccessError, что может привести к сбою приложения. Один из подходов к избеганию подобных проблем — использование уникального имени пакета для классов инструментирования.

Спецификация Java™ Virtual Machine указывает, что последующая попытка разрешить символическую ссылку, которую виртуальная машина Java ранее безуспешно пыталась разрешить, всегда завершается той же ошибкой, что и первоначальная попытка разрешения. Следовательно, если JAR-файл содержит запись, соответствующую классу, для которого виртуальная машина Java безуспешно пыталась разрешить ссылку, то последующие попытки разрешить эту ссылку завершатся той же ошибкой, что и первоначальная попытка.

Параметры:
jarfile - файл JAR, который будет просматриваться, когда загрузчик Bootstrap безуспешно ищет класс.
Исключения:
NullPointerException - если jarfile null.
С момента:
1.6
См. также:
appendToSystemClassLoaderSearch(java.util.jar.JarFile), ClassLoader, JarFile

appendToSystemClassLoaderSearch

void appendToSystemClassLoaderSearch(JarFile jarfile)

Указывает файл JAR с классами инструментирования, которые должны быть определены загрузчиком системы. Когда загрузчик системы для делегирования (см. getSystemClassLoader()) безуспешно ищет класс, записи в JarFile также будут просмотрены.

Этот метод можно использовать несколько раз для добавления нескольких файлов JAR для поиска в порядке вызова этого метода.

Агент должен позаботиться о том, чтобы JAR-файл не содержал никаких классов или ресурсов, кроме тех, которые должны быть определены загрузчиком системы в целях инструментирования. Несоблюдение этого предупреждения может привести к неожиданному поведению, которое трудно диагностировать (см. appendToBootstrapClassLoaderSearch).

Загрузчик системы поддерживает добавление файла JAR для поиска, если он реализует метод с именем appendToClassPathForInstrumentation, который принимает один параметр типа java.lang.String. Метод не обязан иметь public доступ.

Имя файла JAR получается путём вызова метода getName() на jarfile и предоставляется в качестве параметра методу appendToClassPathForInstrumentation.

Спецификация Java™ Virtual Machine указывает, что последующая попытка разрешить символическую ссылку, которую виртуальная машина Java ранее безуспешно пыталась разрешить, всегда завершается той же ошибкой, что и первоначальная попытка разрешения. Следовательно, если JAR-файл содержит запись, соответствующую классу, для которого виртуальная машина Java безуспешно пыталась разрешить ссылку, то последующие попытки разрешить эту ссылку завершатся той же ошибкой, что и первоначальная попытка.

Этот метод не изменяет значение java.class.path system property.

Параметры:
jarfile — JAR-файл, который будет проверяться, если системный загрузчик классов неуспешно ищет класс.
Исключения:
UnsupportedOperationException — если системный загрузчик классов не поддерживает добавление JAR-файла для проверки.
NullPointerException — если jarfile имеет значение null.
С тех пор:
1.6
См. также:
appendToBootstrapClassLoaderSearch(java.util.jar.JarFile), ClassLoader.getSystemClassLoader(), JarFile

isNativeMethodPrefixSupported

boolean isNativeMethodPrefixSupported()

Возвращает, поддерживает ли текущая конфигурация JVM установку префикса для методов нативного кода. Возможность установить префикс для метода нативного кода — это необязательная возможность JVM. Установка префикса для метода нативного кода будет поддерживаться только в том случае, если атрибут manifest Can-Set-Native-Method-Prefix установлен в значение true в JAR-файле агента (как описано в спецификации пакета), и JVM поддерживает эту возможность. Во время одной инстанциации одной JVM несколько вызовов этого метода всегда возвращают один и тот же ответ.

Возвращает:
true, если текущая конфигурация JVM поддерживает установку префикса для метода нативного кода, false — в противном случае.
С тех пор:
1.6
См. также:
setNativeMethodPrefix(java.lang.instrument.ClassFileTransformer, java.lang.String)

setNativeMethodPrefix

void setNativeMethodPrefix(ClassFileTransformer transformer,
                           String prefix)

Этот метод изменяет обработку ошибок при разрешении методов нативного кода, позволяя повторно выполнить разрешение с применением префикса к имени. При использовании с ClassFileTransformer это позволяет инструментировать методы нативного кода.

Поскольку методы нативного кода не могут быть напрямую инструментированы (у них нет байткода), они должны быть обернуты в метод, не являющийся методом нативного кода, который можно инструментировать. Например, если у нас есть:

native boolean foo(int x);

Мы могли бы преобразовать файл класса (с ClassFileTransformer во время первоначального определения класса) таким образом, чтобы это стало:

boolean foo(int x) {
     ... record entry to foo ...
     return wrapped_foo(x);
   }

   native boolean wrapped_foo(int x);

Где foo становится обёрткой для фактического метода нативного кода с добавленным префиксом "wrapped_". Обратите внимание, что "wrapped_" — не лучший выбор префикса, так как он, возможно, сформирует имя уже существующего метода, поэтому что-то вроде "$$$MyAgentWrapped$$$_" было бы лучше, но сделало бы эти примеры менее читабельными.

Обёртка позволит собирать данные о вызове метода нативного кода, но теперь проблема заключается в связывании обернутого метода с реализацией нативного кода. То есть, метод wrapped_foo должен быть разрешен к реализации нативного кода foo, которая может быть:

Java_somePackage_someClass_foo(JNIEnv* env, jint x)

Эта функция позволяет указать префикс и обеспечить надлежащее разрешение. В частности, когда стандартное разрешение терпит неудачу, разрешение повторно выполняется с учётом префикса. Есть два способа, как происходит разрешение: явное разрешение с функцией JNI RegisterNatives и обычное автоматическое разрешение. Для RegisterNatives, JVM попытается установить эту связь:

method(foo) -> nativeImplementation(foo)

Когда это терпит неудачу, разрешение будет повторно выполнено с указанным префиксом, добавленным к имени метода, что обеспечит правильное разрешение:

method(wrapped_foo) -> nativeImplementation(foo)

Для автоматического разрешения JVM попытается:

method(wrapped_foo) -> nativeImplementation(wrapped_foo)

Когда это терпит неудачу, разрешение будет повторно выполнено с удалением указанного префикса из имени реализации, что обеспечит правильное разрешение:

method(wrapped_foo) -> nativeImplementation(foo)

Обратите внимание, что так как префикс используется только при неудачном стандартном разрешении, методы нативного кода могут быть обернуты выборочно.

Поскольку каждый ClassFileTransformer может выполнять собственное преобразование байткода, может быть применено более одного уровня обёрток. Таким образом, каждый трансформер нуждается в собственном префиксе. Поскольку преобразования применяются в порядке, префиксы, если применяются, будут применяться в том же порядке (см. addTransformer). Таким образом, если три трансформера применили обёртки, foo может стать $trans3_$trans2_$trans1_foo. Но если, например, второй трансформер не применил обёртку к foo, он останется просто $trans3_$trans1_foo. Чтобы эффективно определить последовательность префиксов, промежуточный префикс применяется только в том случае, если существует его не-метод-нативного кода обёртка. Таким образом, в последнем примере, даже если $trans1_foo не является методом нативного кода, префикс $trans1_ применяется, так как $trans1_foo существует.

Параметры:
transformer — ClassFileTransformer, который оборачивает с использованием этого префикса.
prefix — Префикс, который необходимо применить к обернутым методам нативного кода при повторной попытке неудачного разрешения метода нативного кода. Если префикс равен либо null, либо пустой строке, то неудачные разрешения методов нативного кода для этого трансформера не повторяются.
Исключения:
NullPointerException — если передан трансформер null.
UnsupportedOperationException — если текущая конфигурация JVM не позволяет установить префикс метода нативного кода (isNativeMethodPrefixSupported() имеет значение false).
IllegalArgumentException — если трансформер не зарегистрирован (см. addTransformer).
С тех пор:
1.6

© 1993, 2020, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API