Пакет java.lang.instrument
Агент развертывается в виде JAR-файла. Атрибут в манифесте JAR-файла указывает на класс агента, который будет загружен для запуска агента. Агенты могут запускаться несколькими способами:
Для реализаций, поддерживающих командную строку, агент может быть запущен, указав опцию в командной строке.
Реализация может поддерживать механизм запуска агентов некоторое время после запуска JVM. Например, реализация может предоставить механизм, который позволяет инструменту присоединиться к работающему приложению и инициировать загрузку агента инструмента в работающее приложение.
Агент может быть упакован с приложением в исполняемый JAR-файл.
Агенты могут преобразовывать классы произвольным образом во время загрузки, преобразовывать модули или преобразовывать байт-код методов уже загруженных классов. Разработчики или администраторы, которые развертывают агенты, развертывают приложения, которые упаковывают агента с приложением, или используют инструменты, которые загружают агентов в работающее приложение, несут ответственность за проверку надежности каждого агента, включая содержимое и структуру JAR-файла агента.
Три способа запуска агента описаны ниже.
Запуск агента из командной строки
Где реализация предоставляет возможность запуска агентов из командной строки, агент запускается путем добавления следующей опции в командную строку:
-javaagent:<jarpath>[=<options>]
где <jarpath> - путь к JAR-файлу агента, а <options> - опции агента. Манифест JAR-файла агента должен содержать атрибут
Premain-Class в своем главном манифесте. Значение этого атрибута - имя класса агента. Класс агента должен реализовывать публичный статический метод premain, аналогичный по принципу точке входа приложения main. После инициализации Java Virtual Machine (JVM) будет вызван метод premain, а затем реальный метод приложения main. Метод premain должен возвратить результат, чтобы запуск продолжился.
Метод premain имеет одну из двух возможных сигнатур. JVM сначала пытается вызвать следующий метод в классе агента:
public static void premain(String agentArgs, Instrumentation inst)
Если класс агента не реализует этот метод, JVM попытается вызвать:
public static void premain(String agentArgs)
Класс агента также может иметь метод agentmain для использования, когда агент запускается после запуска JVM (см. ниже). Когда агент запускается с помощью опции командной строки, метод agentmain не вызывается.
Каждый агент получает свои опции агента через параметр agentArgs. Опции агента передаются как строка, любое дополнительное разбиение должно выполняться самим агентом.
Если агент не может быть запущен (например, потому, что класс агента не может быть загружен или потому, что класс агента не имеет соответствующего метода premain), JVM прервется. Если метод premain выбрасывает необработанное исключение, JVM прервется.
Реализация не обязана предоставлять способ запуска агентов из командной строки. Когда она это делает, тогда она поддерживает опцию -javaagent как указано выше. Опция -javaagent может использоваться несколько раз в одной командной строке, тем самым запуская несколько агентов. Методы premain будут вызываться в том порядке, в котором агенты указаны в командной строке. Более одного агента могут использовать один и тот же <jarpath>.
Нет никаких ограничений моделирования на то, что агент premain метод может сделать. Все, что может сделать приложение main, в том числе создание потоков, является законным для premain.
Запуск агента после запуска JVM
Реализация может предоставить механизм запуска агентов некоторое время после запуска JVM. Подробности о том, как это инициируется, зависят от реализации, но обычно приложение уже запущено, и его метод main уже вызван. В тех случаях, когда реализация поддерживает запуск агентов после запуска JVM, применимо следующее:
Манифест JAR-файла агента должен содержать атрибут
Agent-Classв его основном манифесте. Значение этого атрибута - имя класса агента.Класс агента должен реализовывать публичный статический метод
agentmain.
Метод agentmain имеет одну из двух возможных сигнатур. JVM сначала пытается вызвать следующий метод в классе агента:
public static void agentmain(String agentArgs, Instrumentation inst)
Если класс агента не реализует этот метод, JVM попытается вызвать:
public static void agentmain(String agentArgs)
Класс агента также может иметь метод premain для использования, когда агент запускается с помощью опции командной строки. Когда агент запускается после запуска JVM, метод premain не вызывается.
Агенту передаются его опции агента через параметр agentArgs. Опции агента передаются как строка, любое дополнительное разбиение должно выполняться самим агентом.
Метод agentmain должен выполнять любую необходимую инициализацию, необходимую для запуска агента. По завершении запуска метод должен возвратить результат. Если агент не может быть запущен (например, потому, что класс агента не может быть загружен или потому, что класс агента не имеет соответствующего метода agentmain), JVM не прервется. Если метод agentmain вызывает необработанное исключение, оно будет проигнорировано (но может быть записано JVM для целей отладки).
Включение агента в исполняемый JAR-файл
Спецификация JAR-файлов определяет атрибуты манифеста для автономных приложений, упакованных в виде исполняемых JAR-файлов. Если реализация поддерживает механизм запуска приложения в виде исполняемого JAR-файла, то в основном манифесте может быть включен атрибут Launcher-Agent-Class для указания имени класса агента, который нужно запустить перед вызовом метода приложения main. Виртуальная машина Java пытается вызвать следующий метод в классе агента:
public static void agentmain(String agentArgs, Instrumentation inst)
Если класс агента не реализует этот метод, JVM попытается вызвать:
public static void agentmain(String agentArgs)
Значение параметра agentArgs всегда пустая строка.
Метод agentmain должен выполнить любую необходимую инициализацию, необходимую для запуска агента, и вернуть результат. Если агент не может быть запущен, например, класс агента не может быть загружен, класс агента не определяет соответствующий метод agentmain, или метод agentmain вызывает необработанное исключение или ошибку, JVM прервется.
Загрузка классов агентов и модулей/классов, доступных классу агента
Классы, загруженные из JAR-файла агента, загружаются системным загрузчиком классов и являются членами безымянного модуля системного загрузчика классов. Системный загрузчик классов, как правило, определяет класс, содержащий метод приложения main тоже.
Классы, видимые классу агента, - это классы, видимые системному загрузчику классов, и, по меньшей мере, включают:
Классы в пакетах, экспортированных модулями в базовом слое boot layer. Будет ли базовый слой содержать все платформенные модули или нет, зависит от начального модуля или от того, как было запущено приложение.
Классы, которые могут быть определены системным загрузчиком классов (обычно путём указания пути), чтобы быть членами его безымянного модуля.
Любые классы, которые агент организует для определения загрузчиком базовых классов, чтобы быть членами его безымянного модуля.
Если классам агентов необходимо связаться с классами платформенных (или других) модулей, которые не находятся в базовом слое, то приложение может потребоваться запустить таким образом, чтобы эти модули были в базовом слое. Например, в реализации JDK можно использовать опцию командной строки --add-modules для добавления модулей в набор корневых модулей для разрешения при запуске.
Поддерживаемые классы, которые агент организует для загрузки загрузчиком базовых классов (посредством appendToBootstrapClassLoaderSearch или атрибута Boot-Class-Path ниже), должны связываться только с классами, определенными загрузчиком базовых классов. Нет никакой гарантии, что все платформенные классы могут быть определены загрузчиком базовых классов.
Если настроен пользовательский системный загрузчик классов (с помощью системной переменной java.system.class.loader как указано в методе getSystemClassLoader), то он должен определять метод appendToClassPathForInstrumentation как указано в appendToSystemClassLoaderSearch. Другими словами, пользовательский системный загрузчик классов должен поддерживать механизм добавления JAR-файла агента в поиск системного загрузчика классов.
Атрибуты манифеста
Для JAR-файла агента определены следующие атрибуты манифеста:
Premain-Class- При указании агента во время запуска JVM этот атрибут указывает класс агента. То есть, класс, содержащий метод
premain. При указании агента во время запуска JVM этот атрибут обязателен. Если атрибут отсутствует, JVM завершит работу. Примечание: это имя класса, а не имя файла или путь.Agent-Class- Если реализация поддерживает механизм запуска агентов после запуска виртуальной машины, то этот атрибут указывает класс агента. То есть, класс, содержащий метод
agentmain. Этот атрибут обязателен; если он отсутствует, агент не будет запущен. Примечание: это имя класса, а не имя файла или путь.Launcher-Agent-Class- Если реализация поддерживает механизм запуска приложения как исполняемого JAR-файла, то основной манифест может содержать этот атрибут для указания имени класса агента, который должен быть запущен до вызова метода приложения
main.Boot-Class-Path- Список путей, которые будет искать загрузчик базовых классов. Пути представляют собой каталоги или библиотеки (обычно на многих платформах это JAR- или ZIP-библиотеки). Эти пути ищутся загрузчиком базовых классов после того, как платформенно-специфичные механизмы поиска класса потерпят неудачу. Пути ищутся в указанном порядке. Пути в списке разделяются одной или несколькими пробелами. Путь имеет синтаксис компонента пути иерархического URI. Путь является абсолютным, если он начинается с символа косой черты ('/'), в противном случае он является относительным. Относительный путь разрешается по отношению к абсолютному пути JAR-файла агента. Неправильные и несуществующие пути игнорируются. При запуске агента после запуска виртуальной машины пути, не представляющие 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 игнорируется. Аналогично, если агент запускается после запуска виртуальной машины, то атрибут Agent-Class указывает имя класса агента (значение атрибута Premain-Class игнорируется).
Инструментирование кода в модулях
Для помощи агентам, развёртывающим вспомогательные классы в пути поиска загрузчика базовых классов или в пути поиска загрузчика, загружающего основной класс агента, виртуальная машина Java обеспечивает чтение модуля преобразованных классов модулем без имени обоих загрузчиков.
- Since:
- 1.5
| Класс | Описание |
|---|---|
| ClassDefinition | Этот класс служит блоком параметров для метода Instrumentation.redefineClasses. |
| ClassFileTransformer | Преобразователь файлов классов. |
| IllegalClassFormatException | Выбрасывается реализацией ClassFileTransformer.transform, когда её входные параметры некорректны. |
| Instrumentation | Этот класс предоставляет сервисы, необходимые для инструментирования кода языка программирования Java. |
| UnmodifiableClassException | Выбрасывается реализацией Instrumentation.redefineClasses, когда один из указанных классов не может быть изменён. |
| UnmodifiableModuleException | Выбрасывается для обозначения того, что модуль не может быть изменён. |
© 1993, 2021, 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/17/docs/api/java.instrument/java/lang/instrument/package-summary.html