Интерфейс Instrumentation
public interface Instrumentation
Этот класс предоставляет службы, необходимые для инструментирования кода языка программирования Java. Инструментирование — это добавление байткодов к методам для сбора данных, которые будут использоваться инструментами. Поскольку изменения носят чисто аддитивный характер, эти инструменты не изменяют состояние или поведение приложения. Примеры таких безвредных инструментов включают агенты мониторинга, профилировщики, анализаторы покрытия и логические регистраторы событий.
Существует два способа получения экземпляра интерфейса Instrumentation:
Когда JVM запускается таким образом, что указывает класс агента. В этом случае экземпляр
Instrumentationпередаётся методуpremainкласса агента.-
Когда JVM предоставляет механизм для запуска агентов некоторое время после запуска JVM. В этом случае экземпляр
Instrumentationпередаётся методуagentmainкода агента.
Эти механизмы описаны в спецификации пакета.
После того, как агент приобретает экземпляр Instrumentation , агент может вызывать методы экземпляра в любое время.
- Since:
- 1.5
Методы
| Модификатор и тип | Метод | Описание |
|---|---|---|
void | addTransformer(ClassFileTransformer transformer) | Регистрирует предоставленный преобразователь. |
void | addTransformer(ClassFileTransformer transformer,
boolean canRetransform) | Регистрирует предоставленный преобразователь. |
void | appendToBootstrapClassLoaderSearch(JarFile jarfile) | Определяет JAR-файл с классами инструментирования, которые должны быть определены загрузчиком начального класса. |
void | appendToSystemClassLoaderSearch(JarFile jarfile) | Определяет JAR-файл с классами инструментирования, которые должны быть определены системным загрузчиком классов. |
Class[] | getAllLoadedClasses() | Возвращает массив всех классов, которые в настоящее время загружены JVM. |
Class[] | getInitiatedClasses(ClassLoader loader) | Возвращает массив всех классов, для которых |
long | getObjectSize(Object objectToSize) | Возвращает зависящую от реализации приблизительную оценку объема памяти, занимаемой указанным объектом. |
boolean | isModifiableClass(Class<?> theClass) | Проверяет, может ли класс быть изменён с помощью повторной трансформации или переопределения. |
boolean | isModifiableModule(Module module) | Проверяет, может ли модуль быть изменён с помощью |
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. Повторное преобразование будет поддерживаться только в том случае, если атрибут manifest Can-Retransform-Classes установлено в true в файле JAR-агента (как описано в спецификации пакета) и JVM поддерживает эту возможность. Во время одного экземпляра одного JVM многократные вызовы этого метода всегда возвращают один и тот же ответ.
- Возвращает:
- true, если текущая конфигурация JVM поддерживает повторное преобразование классов, false — в противном случае.
- С:
- 1.6
- См. также:
retransformClasses(java.lang.Class<?>...)
retransformClasses
void retransformClasses(Class<?>... classes)
throws UnmodifiableClassException Повторное преобразование указанного набора классов.
Эта функция облегчает инструментирование уже загруженных классов. Когда классы изначально загружаются или когда они переопределяются, исходные байты файла класса могут быть преобразованы с помощью ClassFileTransformer. Эта функция повторно запускает процесс преобразования (независимо от того, происходило ли преобразование ранее). Это повторное преобразование выполняется следующим образом:
- начиная с исходных байтов файла класса
- для каждого преобразователя, который был добавлен с
canRetransformравным false, байты, возвращаемыеtransformво время последней загрузки или переопределения класса, повторно используются в качестве результата преобразования; обратите внимание, что это эквивалентно повторному применению предыдущего преобразования без изменений; за исключением того, чтоtransformметод не вызывается. - для каждого преобразователя, который был добавлен с
canRetransformравным true, вызывается методtransform - преобразованные байты файла класса устанавливаются в качестве нового определения класса
Порядок преобразования описан в ClassFileTransformer. Этот же порядок используется при автоматическом повторном применении преобразований, неспособных к повторному преобразованию.
Исходные байты файла класса представляют собой байты, переданные в ClassLoader.defineClass или redefineClasses (до применения каких-либо преобразований), однако они могут не совпадать точно. Пул констант может не иметь такой же структуры или содержимого. Пул констант может содержать больше или меньше элементов. Элементы пула констант могут быть в другом порядке; однако индексы пула констант в байткодах методов будут соответствовать. Некоторые атрибуты могут отсутствовать. В случаях, когда порядок не имеет значения, например, порядок методов, он может не сохраняться.
Этот метод работает со множеством классов для возможности одновременных взаимозависимых изменений более чем для одного класса (повторное преобразование класса А может потребовать повторного преобразования класса Б).
Если преобразованный метод имеет активные фреймы стека, эти активные фреймы продолжают выполнять байткоды исходного метода. Преобразованный метод будет использоваться при новых вызовах.
Этот метод не вызывает никаких инициализаций, за исключением тех, которые происходят по обычным правилам JVM. Другими словами, переопределение класса не приводит к выполнению его инициализаторов. Значения статических переменных останутся такими же, как до вызова.
Экземпляры преобразованного класса не затрагиваются.
Повторное преобразование может изменить тела методов, пул констант и атрибуты (если явно не запрещено). Повторное преобразование не должно добавлять, удалять или переименовывать поля или методы, изменять сигнатуры методов или изменять наследование. Повторное преобразование не должно изменять атрибуты NestHost или NestMembers. Эти ограничения могут быть сняты в будущих версиях. Байты файла класса не проверяются, не верифицируются и не устанавливаются до тех пор, пока не будут применены преобразования, если результирующие байты содержат ошибки, этот метод выбросит исключение.
Если этот метод генерирует исключение, ни один класс не был преобразован.
Этот метод предназначен для использования в инструментировании, как описано в спецификации класса.
- Параметры:
-
classes- массив классов для повторного преобразования; массив нулевой длины допускается, в этом случае этот метод ничего не делает - Исключения:
-
UnmodifiableClassException- если указанный класс не может быть изменён (isModifiableClass(java.lang.Class<?>)вернётfalse) -
UnsupportedOperationException- если текущая конфигурация JVM не позволяет повторного преобразования (isRetransformClassesSupported()равно false) или повторное преобразование пытается выполнить неподдерживаемые изменения -
ClassFormatError- если данные не содержали допустимый класс -
NoClassDefFoundError- если имя в файле класса не равно имени класса -
UnsupportedClassVersionError- если номера версий файла класса не поддерживаются -
ClassCircularityError- если новые классы содержат цикличность -
LinkageError- если произошла ошибка связи -
NullPointerException- если переданный массив классов или любой из его компонентовnull. - С:
- 1.6
- См. также:
-
isRetransformClassesSupported(),addTransformer(java.lang.instrument.ClassFileTransformer, boolean),ClassFileTransformer
isRedefineClassesSupported
boolean isRedefineClassesSupported()
Возвращает значение, указывающее, поддерживает ли текущая конфигурация JVM переопределение классов. Возможность переопределения уже загруженного класса является необязательной функцией JVM. Переопределение будет поддерживаться только в том случае, если атрибут manifest Can-Redefine-Classes установлено в true в файле JAR-агента (как описано в спецификации пакета) и JVM поддерживает эту возможность. Во время одного экземпляра одного JVM многократные вызовы этого метода всегда возвращают один и тот же ответ.
- Возвращает:
- true, если текущая конфигурация JVM поддерживает переопределение классов, false — в противном случае.
- См. также:
redefineClasses(java.lang.instrument.ClassDefinition...)
redefineClasses
void redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException,
UnmodifiableClassException Переопределите предоставленный набор классов с использованием предоставленных файлов классов.
Этот метод используется для замены определения класса без ссылки на существующие байты файла класса, как это можно сделать при повторной компиляции из исходного кода для отладки «fix-and-continue». В тех случаях, когда существующие байты файла класса должны быть преобразованы (например, при инструментировании байткода) следует использовать retransformClasses.
Этот метод работает с набором, чтобы позволить одновременные изменения более чем одному классу (переопределение класса A может потребовать переопределения класса B).
Если переопределенный метод имеет активные кадры стека, эти активные кадры продолжают выполнять байткоды исходного метода. Переопределенный метод будет использоваться при новых вызовах.
Этот метод не вызывает никакой инициализации, кроме той, которая произошла бы в соответствии с обычной семантикой JVM. Другими словами, переопределение класса не приводит к выполнению его инициализаторов. Значения статических переменных останутся такими, какими они были до вызова.
Экземпляры переопределенного класса не затрагиваются.
Переопределение может изменить тела методов, пул констант и атрибуты (если это не запрещено явно). Переопределение не должно добавлять, удалять или переименовывать поля или методы, изменять сигнатуры методов или изменять наследование. Переопределение не должно изменять атрибуты NestHost или NestMembers. Эти ограничения могут быть сняты в будущих версиях. Байты файла класса не проверяются, не верифицируются и не устанавливаются до тех пор, пока не будут применены все преобразования. Если полученные байты содержат ошибку, этот метод выбросит исключение.
Если этот метод выбросит исключение, ни один класс не был переопределен.
Этот метод предназначен для использования в инструментировании, как описано в спецификации класса.
- Параметры:
-
definitions- массив классов для переопределения с соответствующими определениями; разрешен массив нулевой длины, в этом случае этот метод ничего не делает - Исключения:
-
UnmodifiableClassException- если указанный класс не может быть изменён (isModifiableClass(java.lang.Class<?>)вернётfalse) -
UnsupportedOperationException- если текущая конфигурация JVM не позволяет переопределять (isRedefineClassesSupported()ложно) или переопределение пыталось произвести неподдерживаемые изменения -
ClassFormatError- если данные не содержали допустимого класса -
NoClassDefFoundError- если имя в файле класса не равно имени класса -
UnsupportedClassVersionError- если номера версий файла класса не поддерживаются -
ClassCircularityError- если новые классы содержат цикличность -
LinkageError- если произошла ошибка связи -
NullPointerException- если предоставленный массив определений или любой из его компонентовnull -
ClassNotFoundException- никогда не может быть выброшено (присутствует только для совместимости) - См. также:
-
isRedefineClassesSupported(),addTransformer(java.lang.instrument.ClassFileTransformer, boolean),ClassFileTransformer
isModifiableClass
boolean isModifiableClass(Class<?> theClass)
Проверяет, может ли класс быть изменён с помощью повторного преобразования или переопределения. Если класс может быть изменён, этот метод возвращает true. Если класс не может быть изменён, этот метод возвращает false.
Для того, чтобы класс мог быть повторно преобразован, isRetransformClassesSupported() также должно быть истинно. Но значение isRetransformClassesSupported() не влияет на значение, возвращаемое этой функцией. Для того, чтобы класс мог быть переопределён, isRedefineClassesSupported() также должно быть истинно. Но значение isRedefineClassesSupported() не влияет на значение, возвращаемое этой функцией.
Примитивные классы (например, java.lang.Integer.TYPE) и массивы никогда не могут быть изменены.
- Параметры:
-
theClass- класс, который нужно проверить на возможность изменения - Возвращает:
- является ли класс аргумента изменяемым
- Исключения:
-
NullPointerException- если указанный класс являетсяnull. - С:
- 1.6
- См. также:
-
retransformClasses(java.lang.Class<?>...),isRetransformClassesSupported(),redefineClasses(java.lang.instrument.ClassDefinition...),isRedefineClassesSupported()
getAllLoadedClasses
Class[] getAllLoadedClasses()
Возвращает массив всех классов, в настоящее время загруженных JVM.
- Возвращает:
- массив, содержащий все классы, загруженные JVM; нулевой длины, если их нет
getInitiatedClasses
Class[] getInitiatedClasses(ClassLoader loader)
Возвращает массив всех классов, для которых loader является инициализирующим загрузчиком. Если предоставленный загрузчик null, возвращаются классы, инициализированные загрузчиком bootstrap.
- Параметры:
-
loader- загрузчик, чья инициализированная коллекция классов будет возвращена - Возвращает:
- массив, содержащий все классы, для которых загрузчик является инициализирующим загрузчиком; нулевой длины, если таких классов нет
getObjectSize
long getObjectSize(Object objectToSize)
Возвращает зависящее от реализации приблизительное значение памяти, потребляемой указанным объектом. Результат может включать часть или все накладные расходы объекта, и поэтому полезен для сравнения внутри одной реализации, но не между реализациями. Оценка может изменяться во время одного вызова JVM.
- Параметры:
-
objectToSize- объект, размер которого требуется - Возвращает:
- зависимое от реализации приблизительное значение памяти, потребляемой указанным объектом
- Исключения:
-
NullPointerException- если предоставленный объектnull.
appendToBootstrapClassLoaderSearch
void appendToBootstrapClassLoaderSearch(JarFile jarfile)
Указывает JAR-файл с классами инструментирования, которые будут определяться загрузчиком bootstrap.
Когда встроенный загрузчик классов виртуальной машины, известный как «загрузчик bootstrap», неуспешно ищет класс, входящие в JAR file также будут проверены.
Этот метод может быть использован несколько раз для добавления нескольких JAR-файлов, которые будут проверяться в порядке вызова этого метода.
Агент должен позаботиться о том, чтобы JAR-файл не содержал никаких классов или ресурсов, кроме тех, которые должны быть определены загрузчиком bootstrap для целей инструментирования. Несоблюдение этого предупреждения может привести к непредсказуемому поведению, которое сложно диагностировать. Например, предположим, что существует загрузчик L, а родитель L для делегирования - загрузчик bootstrap. Кроме того, метод в классе C, определенном L, ссылается на закрытый класс-аксессор C$1. Если JAR-файл содержит класс C$1, то делегирование загрузчику bootstrap вызовет определение C$1 загрузчиком bootstrap. В этом примере будет брошено исключение IllegalAccessError, которое может привести к ошибке приложения. Один из способов избежать таких проблем - использовать уникальное имя пакета для классов инструментирования.
Спецификация виртуальной машины Java™ указывает, что последующая попытка разрешить символическую ссылку, которую виртуальная машина 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.
- 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. Настройка префикса метода нативного кода будет поддерживаться только в том случае, если атрибут manifest 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()ложь). -
IllegalArgumentException- если трансформатор не зарегистрирован (см.addTransformer). - Since:
- 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
© 1993, 2020, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/11/docs/api/java.instrument/java/lang/instrument/Instrumentation.html