Пакет java.lang.instrument
Файлы классов, составляющие агента, упакованы в JAR-файл, либо вместе с приложением в исполняемом JAR-файле, или чаще, как отдельный JAR-файл, называемый JAR-файлом агента. Атрибут в главном манифесте JAR-файла идентифицирует один из файлов классов в JAR-файле как класс агента. Класс агента определяет специальный метод, который JVM вызывает для запуска агента.
Агенты, которые упакованы с приложением в исполняемом JAR-файле, запускаются во время запуска JVM. Агенты, которые упакованы в JAR-файл агента, могут быть запущены во время запуска JVM через опцию командной строки, или, где это поддерживается реализацией, запущены в работающей JVM.
Агенты могут преобразовывать классы произвольными способами во время загрузки, преобразовывать модули или преобразовывать байт-код методов уже загруженных классов. Разработчики или администраторы, которые развертывают агенты, развертывают приложения, которые упаковывают агента с приложением, или используют инструменты, которые загружают агентов в работающее приложение, несут ответственность за проверку надёжности каждого агента, включая содержимое и структуру JAR-файла агента.
Запуск агента
Запуск агента, упакованного с приложением в исполняемый JAR-файл
Спецификация JAR-файлов определяет атрибуты манифеста для автономных приложений, которые упакованы как исполняемые JAR-файлы. Если реализация поддерживает механизм запуска приложения как исполняемого JAR-файла, то главный манифест JAR-файла может содержать атрибут Launcher-Agent-Class для указания двоичного имени класса Java-агента, который упакован с приложением. Если атрибут присутствует, тогда JVM запускает агента, загружая класс агента и вызывая его метод agentmain. Метод вызывается до вызова метода приложения main. Метод agentmain имеет одну из двух возможных сигнатур. JVM сначала пытается вызвать следующий метод в классе агента:
public static void agentmain(String agentArgs, Instrumentation inst)
Если класс агента не определяет этот метод, тогда JVM попытается вызвать:
public static void agentmain(String agentArgs)
Значение параметра agentArgs всегда пустая строка. В первом методе параметр inst — объект Instrumentation, который агент может использовать для инструментации кода.
Метод agentmain должен выполнить все необходимые инициализации для запуска агента и вернуть значение. Если агент не может быть запущен, например, класс агента не может быть загружен, класс агента не определяет соответствующий метод agentmain, или метод agentmain выбрасывает необработанное исключение или ошибку, JVM прервётся до вызова метода приложения main.
Запуск агента из командной строки
Там, где реализация предоставляет способ запуска агентов из командной строки, JAR-файл агента указывается с помощью следующей опции командной строки:
-javaagent:<jarpath>[=<options>]
где <jarpath> — путь к JAR-файлу агента, а <options> — опции агента. Главный манифест JAR-файла агента должен содержать атрибут
Premain-Class. Значение этого атрибута — двоичное имя класса агента в JAR-файле. JVM запускает агента, загружая класс агента и вызывая его метод premain. Метод вызывается до вызова метода приложения main. Метод premain имеет одну из двух возможных сигнатур. JVM сначала пытается вызвать следующий метод в классе агента:
public static void premain(String agentArgs, Instrumentation inst)
Если класс агента не определяет этот метод, тогда JVM попытается вызвать:
public static void premain(String agentArgs)
Агент получает свои опции через параметр agentArgs. Опции агента передаются как строка, любое дополнительное разбиение должно производиться самим агентом. В первом методе параметр inst — объект Instrumentation, который агент может использовать для инструментации кода.
Если агент не может быть запущен, например, класс агента не может быть загружен, класс агента не определяет соответствующий метод premain, или метод
premain выбрасывает необработанное исключение или ошибку, JVM прервётся до вызова метода приложения main.
Реализация не обязана предоставлять способ запуска агентов из командной строки. Когда она это делает, тогда она поддерживает опцию -javaagent как указано выше. Опция -javaagent может быть использована несколько раз в одной командной строке, тем самым запуская несколько агентов. Методы premain будут вызваны в порядке указания агентов в командной строке. Несколько агентов могут использовать один и тот же <jarpath>.
Класс агента также может иметь метод agentmain для использования при запуске агента после запуска JVM (см. ниже). Когда агент запускается с помощью опции командной строки, метод agentmain не вызывается.
Запуск агента в работающей JVM
Реализация может предоставить механизм запуска агентов в работающей JVM (после запуска JVM). Подробности о том, как это инициируется, зависят от реализации, но обычно приложение уже запущено, и его метод main уже вызван. Там, где реализация поддерживает запуск агента в работающей JVM, применяется следующее:
Класс агента должен быть упакован в JAR-файл агента. Главный манифест JAR-файла агента должен содержать атрибут
Agent-Class. Значение этого атрибута — двоичное имя класса агента в JAR-файле.Класс агента должен определять публичный статический метод
agentmain.-
JVM выводит предупреждение в стандартный поток ошибок для каждого агента, который она пытается запустить в работающей JVM. Если агент был ранее запущен (при запуске JVM или в работающей JVM), то способ отображения предупреждения при попытке запуска того же агента второй или последующий раз зависит от реализации. Предупреждения могут быть отключены с помощью опции командной строки, специфичной для реализации.
Примечание реализации: Для виртуальной машины HotSpot используется опция JVM
-XX:+EnableDynamicAgentLoadingдля разрешения динамической загрузки агентов в работающую JVM. Эта опция подавляет вывод предупреждения в стандартный поток ошибок при запуске агента в работающей JVM.
JVM запускает агента, загружая класс агента и вызывая его метод
agentmain. Метод agentmain имеет одну из двух возможных сигнатур. JVM сначала пытается вызвать следующий метод в классе агента:
public static void agentmain(String agentArgs, Instrumentation inst)
Если класс агента не определяет этот метод, тогда JVM попытается вызвать:
public static void agentmain(String agentArgs)
Агент получает свои опции через параметр agentArgs. Опции агента передаются как строка, любое дополнительное разбиение должно производиться самим агентом. В первом методе параметр inst — объект Instrumentation, который агент может использовать для инструментации кода.
Метод agentmain должен выполнить все необходимые инициализации для запуска агента. После завершения запуска метод должен вернуть значение. Если агент не может быть запущен (например, потому что класс агента не может быть загружен или потому что класс агента не имеет соответствующего метода agentmain), JVM не прервётся. Если метод agentmain выбрасывает необработанное исключение, оно будет проигнорировано (но может быть залогировано JVM для целей отладки).
Класс агента также может иметь метод premain для использования, когда агент запускается с помощью опции командной строки. Метод premain не вызывается, когда агент запускается в работающей JVM.
Загрузка классов агента и модулей/классов, доступных классу агента
Классы, загруженные из JAR-файла агента, загружаются системным загрузчиком классов и являются членами безымянного модуля системного загрузчика классов. Системный загрузчик классов обычно определяет класс, содержащий метод приложения main тоже.
Классы, видимые классу агента, — это классы, видимые системному загрузчику классов, и минимально включают:
Классы в пакетах, экспортированных модулями в слое загрузки. Содержит ли слой загрузки все платформенные модули или нет, зависит от начального модуля или способа запуска приложения.
Классы, которые могут быть определены системным загрузчиком классов (обычно путь к классу) для того, чтобы быть членами его безымянного модуля.
Любые классы, которые агент организует, чтобы быть определёнными загрузчиком bootstrap-классов для того, чтобы быть членами его безымянного модуля.
Если классы агента должны ссылаться на классы в платформенных (или других) модулях, которые не находятся в слое загрузки, то приложение может потребовать запуска таким образом, чтобы эти модули были в слое загрузки. Например, в реализации JDK опция командной строки --add-modules может использоваться для добавления модулей в набор корневых модулей для разрешения при запуске.
Поддерживающие классы, которые агент организует для загрузки загрузчиком bootstrap-классов (с помощью appendToBootstrapClassLoaderSearch или атрибута Boot-Class-Path ниже), должны ссылаться только на классы, определённые загрузчиком bootstrap-классов. Нет гарантии, что все платформенные классы могут быть определены загрузчиком boot-классов.
Если конфигурируется пользовательский загрузчик системных классов (с помощью системной переменной java.system.class.loader как указано в методе getSystemClassLoader) , то он должен определить метод appendToClassPathForInstrumentation как указано в appendToSystemClassLoaderSearch. Другими словами, пользовательский загрузчик системных классов должен поддерживать механизм добавления JAR-файла агента в поиск загрузчика системных классов.
Атрибуты манифеста JAR-файла
Следующие атрибуты в основной секции манифеста JAR-файла приложения или агента определены для Java-агентов:
Launcher-Agent-Class- Если реализация поддерживает механизм запуска приложения в исполняемом JAR-файле, то этот атрибут, если он присутствует, указывает имя класса агента в двоичном формате, упакованного с приложением. Агент запускается путем вызова метода класса агента
agentmain. Он вызывается до вызова метода приложенияmain.Premain-Class- Если JAR-файл агента указан во время запуска JVM, этот атрибут указывает имя класса агента в двоичном формате в JAR-файле. Агент запускается путем вызова метода класса агента
premain. Он вызывается до вызова метода приложенияmain. Если атрибут отсутствует, JVM завершит работу.Agent-Class- Если реализация поддерживает механизм запуска агента в какой-то момент после запуска JVM, то этот атрибут указывает имя класса Java-агента в двоичном формате в JAR-файле агента. Агент запускается путем вызова метода класса агента
agentmain. Этот атрибут обязателен; если его нет, агент не будет запущен.Boot-Class-Path- Список путей, которые будут просматриваться загрузчиком Bootstrap. Пути представляют собой каталоги или библиотеки (часто называемые JAR или zip-библиотеками на многих платформах). Эти пути просматриваются загрузчиком Bootstrap после того, как платформенные механизмы поиска класса потерпели неудачу. Пути просматриваются в указанном порядке. Пути в списке разделены одним или несколькими пробелами. Путь принимает синтаксис компонента пути иерархического URI. Путь является абсолютным, если он начинается с символа косой черты ('/'), в противном случае он относительный. Относительный путь разрешается относительно абсолютного пути к JAR-файлу агента. Неправильные и несуществующие пути игнорируются. Когда агент запускается в какой-то момент после запуска JVM, пути, которые не представляют собой JAR-файл, игнорируются. Этот атрибут необязателен.
Can-Redefine-Classes- Булево значение (
trueилиfalse, регистр не важен). Нужна ли возможность переопределения классов, используемых этим агентом. Значения, отличные отtrue, рассматриваются какfalse. Этот атрибут необязателен, по умолчаниюfalse.Can-Retransform-Classes- Булево значение (
trueилиfalse, регистр не важен). Нужна ли возможность повторной трансформации классов, используемых этим агентом. Значения, отличные отtrue, рассматриваются какfalse. Этот атрибут необязателен, по умолчаниюfalse.Can-Set-Native-Method-Prefix- Булево значение (
trueилиfalse, регистр не важен). Нужна ли возможность установки префикса для методов нативных методов, используемых этим агентом. Значения, отличные отtrue, рассматриваются какfalse. Этот атрибут необязателен, по умолчаниюfalse.
JAR-файл агента может иметь как атрибут Premain-Class, так и атрибут
Agent-Class в манифесте. Когда агент запускается из командной строки с помощью опции -javaagent, то атрибут
Premain-Class указывает имя класса агента в двоичном формате, а атрибут
Agent-Class игнорируется. Аналогично, если агент запускается в какой-то момент после запуска JVM, то атрибут Agent-Class указывает имя класса агента в двоичном формате (значение атрибута Premain-Class игнорируется).
Инструментирование кода в модулях
В качестве помощи агентам, которые разворачивают поддерживающие классы в пути поиска загрузчика Bootstrap или в пути поиска загрузчика, загружающего основной класс агента, виртуальная машина Java организует чтение модуля преобразованных классов из безымянного модуля обоих загрузчиков.
- Since:
- 1.5
| Класс | Описание |
|---|---|
| ClassDefinition | Этот класс служит блоком параметров для метода Instrumentation.redefineClasses. |
| ClassFileTransformer | Трансформатор файлов классов. |
| IllegalClassFormatException | Выбрасывается реализацией ClassFileTransformer.transform, когда ее входные параметры неверны. |
| Instrumentation | Этот класс предоставляет службы, необходимые для инструментирования кода языка программирования Java. |
| UnmodifiableClassException | Выбрасывается реализацией Instrumentation.redefineClasses, когда один из указанных классов не может быть изменен. |
| UnmodifiableModuleException | Выбрасывается для указания того, что модуль не может быть изменен. |
© 1993, 2023, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/21/docs/api/java.instrument/java/lang/instrument/package-summary.html