Spec-Zone.ru › OpenJDK 21

Интерфейс Instrumentation

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

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

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

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

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

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

Примечание API:
Этот интерфейс не предназначен для реализации вне модуля java.instrument.
С:
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 может найти по имени через ClassLoader::loadClass, Class::forName и связь байткодов.
long getObjectSize(Object objectToSize)
Возвращает приблизительную, зависящую от реализации, оценку объема памяти, занимаемой указанным объектом.
boolean isModifiableClass(Class<?> theClass)
Проверяет, можно ли модифицировать класс с помощью повторной трансформации или переопределения.
boolean isModifiableModule(Module module)
Проверяет, можно ли модифицировать модуль с помощью redefineModule.
boolean isNativeMethodPrefixSupported()
Возвращает, поддерживает ли текущая конфигурация JVM установку префикса для методов нативных.
boolean isRedefineClassesSupported()
Возвращает, поддерживает ли текущая конфигурация JVM переопределение классов.
boolean isRetransformClassesSupported()
Возвращает, поддерживает ли текущая конфигурация JVM повторную трансформацию классов.
void redefineClasses(ClassDefinition... definitions)
Переопределяет указанный набор классов, используя предоставленные файлы классов.
void redefineModule(Module module, Set<Module> extraReads, Map<String,Set<Module>> extraExports, Map<String,Set<Module>> extraOpens, Set<Class<?>> extraUses, Map<Class<?>,List<Class<?>>> extraProvides)
Переопределяет модуль для расширения набора модулей, которые он читает, набора пакетов, которые он экспортирует или открывает, или сервисов, которые он использует или предоставляет.
boolean removeTransformer(ClassFileTransformer transformer)
Отменяет регистрацию предоставленного трансформера.
void retransformClasses(Class<?>... classes)
Повторно преобразует указанный набор классов.
void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix)
Этот метод изменяет обработку ошибок при разрешении нативных методов, позволяя повторную попытку с применением префикса к имени.

Подробное описание методов

addTransformer

void addTransformer(ClassFileTransformer transformer, boolean canRetransform)
Регистрирует предоставленный трансформатор. Все будущие определения классов будут видны трансформатору, за исключением определений классов, от которых какой-либо зарегистрированный трансформатор зависит. Трансформатор вызывается при загрузке классов, при их переопределении и, если canRetransform равно true, при их повторном преобразовании. ClassFileTransformer определяет порядок вызовов преобразования. Если трансформатор генерирует исключение во время выполнения, 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. Повторное преобразование будет поддерживаться только в том случае, если атрибут 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 вызывается в этих трансформаторах
  • преобразованные байты файла класса устанавливаются в качестве нового определения класса

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

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

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

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

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

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

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

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

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

Параметры:
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. Переопределение будет поддерживаться только в том случае, если атрибут Can-Redefine-Classes манифеста установлено в true в JAR-файле агента (как описано в спецификации пакета) и JVM поддерживает эту возможность. В течение одной инстанции одной JVM, множественные вызовы этого метода всегда вернут один и тот же ответ.
Возвращает:
true, если текущая конфигурация JVM поддерживает переопределение классов, false — если нет.
См. также:
  • redefineClasses(java.lang.instrument.ClassDefinition...)

переопределитьКлассы

void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException, UnmodifiableClassException
Переопределить предоставленный набор классов с использованием предоставленных файлов классов.

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

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

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

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

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

Поддерживаемые изменения файла класса описаны в JVM TI RedefineClasses. Байты файла класса не проверяются, не верифицируются и не устанавливаются до тех пор, пока не будут применены преобразования, если полученные байты неверны, этот метод выбросит исключение.

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

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

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

isModifiableClass

boolean isModifiableClass(Class<?> theClass)
Проверяет, можно ли изменить класс с помощью повторной трансформации или переопределения. Если класс изменяемый, этот метод возвращает true. Если класс не изменяемый, этот метод возвращает false.

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

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

Parameters:
theClass - класс, который нужно проверить на возможность изменения
Returns:
можно ли изменить аргумент класса
Throws:
NullPointerException - если указанный класс null.
Since:
1.6
See Also:
  • retransformClasses(java.lang.Class<?>...)
  • isRetransformClassesSupported()
  • redefineClasses(java.lang.instrument.ClassDefinition...)
  • isRedefineClassesSupported()

getAllLoadedClasses

Class[] getAllLoadedClasses()
Возвращает массив всех классов, текущих загруженных JVM. Возвращаемый массив включает все классы и интерфейсы, включая скрытые классы или интерфейсы, и массивы всех типов.
Returns:
массив, содержащий все классы, загруженные JVM, нулевой длины, если их нет

getInitiatedClasses

Class[] getInitiatedClasses(ClassLoader loader)
Возвращает массив всех классов, которые loader может найти по имени через ClassLoader::loadClass, Class::forName и привязку байткода. То есть, все классы, для которых loader был зарегистрирован как инициализирующий загрузчик. Если предоставленный loader null, возвращаются классы, которые загрузчик bootstrap может найти по имени.

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

Parameters:
loader - загрузчик, список инициализированных классов которого будет возвращен
Returns:
массив, содержащий все классы, которые loader может найти по имени; нулевой длины, если их нет

getObjectSize

long getObjectSize(Object objectToSize)
Возвращает зависящую от реализации приблизительную оценку объема памяти, занимаемой указанным объектом. Результат может включать часть или все накладные расходы объекта, и поэтому полезен для сравнения в рамках одной реализации, но не между реализациями. Оценка может меняться во время одного вызова JVM.
Parameters:
objectToSize - объект, размер которого нужно получить
Returns:
зависящая от реализации приблизительная оценка объема памяти, занимаемой указанным объектом
Throws:
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 определяет, что последующая попытка разрешить символическую ссылку, которую виртуальная машина Java ранее безуспешно пыталась разрешить, всегда завершается той же ошибкой, что и в результате первой попытки разрешения. Следовательно, если JAR-файл содержит запись, соответствующую классу, для которого виртуальная машина Java безуспешно пыталась разрешить ссылку, последующие попытки разрешить эту ссылку завершатся той же ошибкой, что и первая попытка.

Parameters:
jarfile - JAR-файл, который будет просматриваться, когда загрузчик bootstrap безуспешно ищет класс.
Throws:
NullPointerException - если jarfile null.
Since:
1.6
See Also:
  • 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 указывает, что последующая попытка разрешить символическую ссылку, которую виртуальная машина Java ранее неудачно пыталась разрешить, всегда завершается ошибкой с тем же сообщением об ошибке, которое было выброшено в результате первой попытки разрешения. Следовательно, если JAR-файл содержит запись, соответствующую классу, для которого виртуальная машина Java неудачно пыталась разрешить ссылку, то последующие попытки разрешить эту ссылку завершатся той же ошибкой, что и первая попытка.

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

Parameters:
jarfile - JAR-файл, который будет просматриваться, когда загрузчик системных классов неудачно ищет класс.
Throws:
UnsupportedOperationException - Если загрузчик системных классов не поддерживает добавление JAR-файла для поиска.
NullPointerException - Если jarfile равно null.
Since:
1.6
See Also:
  • appendToBootstrapClassLoaderSearch(java.util.jar.JarFile)
  • ClassLoader.getSystemClassLoader()
  • JarFile

isNativeMethodPrefixSupported

boolean isNativeMethodPrefixSupported()
Возвращает, поддерживает ли текущая конфигурация JVM установку префикса для методов нативного кода. Возможность установить префикс для метода нативного кода является необязательной функцией JVM. Установка префикса для метода нативного кода будет поддерживаться только в том случае, если атрибут Can-Set-Native-Method-Prefix манифеста установлен в true в JAR-файле агента (как описано в спецификации пакета) и JVM поддерживает эту функцию. Во время одной инстанциации одной JVM несколько вызовов этого метода всегда возвращают один и тот же ответ.
Returns:
true, если текущая конфигурация JVM поддерживает установку префикса для метода нативного кода, false — в противном случае.
Since:
1.6
See Also:
  • 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 существует.

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

Переопределение модуля

void redefineModule(Module module, Set<Module> extraReads, Map<String,Set<Module>> extraExports, Map<String,Set<Module>> extraOpens, Set<Class<?>> extraUses, Map<Class<?>,List<Class<?>>> extraProvides)
Переопределяет модуль для расширения набора модулей, которые он читает, набора пакетов, которые он экспортирует или открывает, или сервисов, которые он использует или предоставляет. Этот метод упрощает инструментирование кода в именованных модулях, когда это инструментирование требует изменений в наборе читаемых модулей, экспортируемых или открытых пакетов или используемых или предоставляемых сервисов.

Этот метод не может уменьшить набор модулей, которые читает модуль, ни уменьшить набор пакетов, которые он экспортирует или открывает, ни уменьшить набор сервисов, которые он использует или предоставляет. Этот метод является бесполезным (no-op), когда вызывается для переопределения безымянного модуля.

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

Параметр extraExports — это карта дополнительных пакетов для экспорта. Параметр extraOpens — это карта дополнительных пакетов для открытия. В обоих случаях, ключ карты — это полное имя пакета, определенное в разделе 6.5.3 спецификации языка Java, например, "java.lang". Значение карты — это непустой набор модулей, для которых пакет должен быть экспортирован или открыт.

Параметр extraProvides — это дополнительные поставщики сервисов для предоставления модулем. Ключ карты — это тип сервиса. Значение карты — это непустой список типов реализации, каждый из которых является членом модуля и реализацией сервиса.

Этот метод безопасен для одновременного использования и позволяет нескольким агентам инструментировать и обновлять один и тот же модуль примерно в одно и то же время.

Параметры:
module - модуль для переопределения
extraReads - возможно пустой набор дополнительных модулей для чтения
extraExports - возможно пустая карта дополнительных пакетов для экспорта
extraOpens - возможно пустая карта дополнительных пакетов для открытия
extraUses - возможно пустой набор дополнительных сервисов для использования
extraProvides - возможно пустая карта дополнительных сервисов для предоставления
Исключения:
IllegalArgumentException - Если extraExports или extraOpens содержит ключ, который не является пакетом в модуле; если extraExports или extraOpens сопоставляет ключ с пустым набором; если значение в карте extraProvides содержит тип поставщика сервиса, который не является членом модуля или реализацией сервиса; или extraProvides сопоставляет ключ с пустым списком
UnmodifiableModuleException - если модуль нельзя изменить
NullPointerException - если любой из аргументов null или любой из наборов или карт содержит null ключ или значение
С:
9
См. также:
  • isModifiableModule(Module)

isModifiableModule

boolean isModifiableModule(Module module)
Проверяет, можно ли изменить модуль с помощью redefineModule. Если модуль изменяем, то этот метод возвращает true. Если модуль неизменяем, то этот метод возвращает false. Этот метод всегда возвращает true когда модуль является безымянным модулем (так как переопределение безымянного модуля является бесполезным действием (no-op)).
Параметры:
module - модуль для проверки возможности его изменения
Возвращает:
true если модуль изменяем, иначе false
Исключения:
NullPointerException - если модуль null
С:
9

© 1993, 2023, 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.
https://docs.oracle.com/en/java/javase/21/docs/api/java.instrument/java/lang/instrument/Instrumentation.html

Spec-Zone.ru

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