Spec-Zone.ru › OpenJDK 24

Интерфейс 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 (до применения каких-либо преобразований), но они могут не совпадать точно. Пул констант может иметь другую структуру или содержимое. Пул констант может содержать больше или меньше записей. Записи пула констант могут быть в другом порядке; однако, индексы пула констант в байткодах методов будут соответствовать. Некоторые атрибуты могут отсутствовать. В местах, где порядок не имеет значения, например, порядок методов, порядок может не сохраняться.

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

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

Этот метод не вызывает никаких инициализаций, кроме тех, которые происходили бы в соответствии с обычными семантиками 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
Переопределяет предоставленный набор классов с использованием предоставленных файлов классов.

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

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

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

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

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

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

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

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

Параметры:
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 может найти по имени через ClassLoader::loadClass, Class::forName и связывание байткода. То есть, все классы, для которых loader был записан как инициализирующий загрузчик. Если предоставленный loader является null, возвращаются классы, которые загрузчик Bootstrap может найти по имени.

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

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

getObjectSize

long getObjectSize(Object objectToSize)
Возвращает зависящую от реализации приблизительную оценку объёма памяти, занимаемой указанным объектом. Результат может включать некоторые или все накладные расходы объекта, и поэтому полезен для сравнения в рамках одной реализации, но не между реализациями. Оценка может изменяться во время одного вызова JVM.
Параметры:
objectToSize - объект, размер которого необходимо определить
Возвращает:
зависимая от реализации приблизительная оценка объёма памяти, занимаемой указанным объектом
Исключения:
NullPointerException - если предоставленный объект является null.

appendToBootstrapClassLoaderSearch

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

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

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

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

Спецификация виртуальной машины Java указывает, что последующая попытка разрешить символическую ссылку, которую виртуальная машина 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 указывает, что последующая попытка разрешения символической ссылки, которую виртуальная машина Java ранее безуспешно пыталась разрешить, всегда завершается ошибкой с той же ошибкой, которая была выброшена в результате первоначальной попытки разрешения. Следовательно, если JAR-файл содержит запись, соответствующую классу, для которого виртуальная машина Java безуспешно пыталась разрешить ссылку, то последующие попытки разрешить эту ссылку завершатся той же ошибкой, что и первоначальная попытка.

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

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

isNativeMethodPrefixSupported

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

Переопределить модуль

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)
Переопределяет модуль для расширения набора модулей, которые он читает, набора пакетов, которые он экспортирует или открывает, или служб, которые он использует или предоставляет. Этот метод облегчает инструментирование кода в именованных модулях, где это инструментирование требует изменений в наборе читаемых модулей, экспортируемых или открытых пакетов, или используемых или предоставляемых служб.

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

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

Параметр 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, когда модуль является безымянным модулем (поскольку переопределение безымянного модуля — это пустая операция).
Параметры:
module — модуль, для которого нужно проверить возможность изменения
Возвращает:
true, если модуль изменяемый, в противном случае false
Исключения:
NullPointerException — если модуль является null
С:
9

© 1993, 2025, 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://download.java.net/java/early_access/jdk24/docs/api/java.instrument/java/lang/instrument/Instrumentation.html

Spec-Zone.ru

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