Spec-Zone.ru › OpenJDK 25

Интерфейс 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(Class...)

retransformClasses

void retransformClasses(Class<?>... classes) throws UnmodifiableClassException
Повторно преобразует переданный набор классов.

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

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

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

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

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

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

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

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

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

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

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

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

isRedefineClassesSupported

boolean isRedefineClassesSupported()
Возвращает значение, указывающее, поддерживает ли текущая конфигурация JVM переопределение классов. Возможность переопределять уже загруженный класс является дополнительной возможностью JVM. Переопределение поддерживается только в том случае, если атрибут манифеста Can-Redefine-Classes имеет значение true в JAR-файле агента (как описано в спецификации пакета) и JVM поддерживает эту возможность. В течение одного экземпляра JVM все вызовы этого метода всегда возвращают один и тот же результат.
Возвращает:
true, если текущая конфигурация JVM поддерживает переопределение классов; в противном случае false.
См. также:
  • redefineClasses(ClassDefinition...)

redefineClasses

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

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

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

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

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

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

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

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

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

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

isModifiableClass

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

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

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

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

getAllLoadedClasses

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

getInitiatedClasses

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

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

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

getObjectSize

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

appendToBootstrapClassLoaderSearch

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

Если встроенный загрузчик классов виртуальной машины, известный как «загрузчик классов начальной загрузки», не может найти класс, также выполняется поиск среди записей в JAR file.

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

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

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

Параметры:
jarfile — JAR-файл, в котором выполняется поиск, если загрузчику классов начальной загрузки не удалось найти класс.
Исключения:
NullPointerException — если jarfile равен null.
Начиная с версии:
1.6
См. также:
  • appendToSystemClassLoaderSearch(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.
Начиная с версии:
1.6
См. также:
  • appendToBootstrapClassLoaderSearch(JarFile)
  • ClassLoader.getSystemClassLoader()
  • JarFile

isNativeMethodPrefixSupported

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

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

redefineModule

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

Сообщить об ошибке или предложить улучшение
Дополнительную справочную информацию по API и документацию для разработчиков см. в разделе документации Java SE, содержащем более подробные описания для разработчиков, обзоры концепций, определения терминов, обходные решения и примеры рабочего кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или ее аффилированных лиц в США и других странах.
Авторские права © 1993, 2025, Oracle и/или ее аффилированные лица, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 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://docs.oracle.com/en/java/javase/25/docs/api/java.instrument/java/lang/instrument/Instrumentation.html

Spec-Zone.ru

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