Интерфейс Instrumentation

public interface Instrumentation

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

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

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

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

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

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

Since:
1.5

Методы

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

Регистрирует предоставленный преобразователь.

void addTransformer​(ClassFileTransformer transformer, boolean canRetransform)

Регистрирует предоставленный преобразователь.

void appendToBootstrapClassLoaderSearch​(JarFile jarfile)

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

void appendToSystemClassLoaderSearch​(JarFile jarfile)

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

Class[] getAllLoadedClasses()

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

Class[] getInitiatedClasses​(ClassLoader loader)

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

long getObjectSize​(Object objectToSize)

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

boolean isModifiableClass​(Class<?> theClass)

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

boolean 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. Повторное преобразование будет поддерживаться только в том случае, если атрибут 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

Spec-Zone .ru
спецификации, руководства, описания, API