Пакет 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 приложения.
Классы, видимые классу агента, — это классы, видимые системному загрузчику классов; к ним как минимум относятся:
Классы в пакетах, экспортируемых модулями начального слоя. Наличие в начальном слое всех модулей платформы зависит от начального модуля и от способа запуска приложения.
Классы, которые системный загрузчик классов может определить (обычно из пути классов) как члены своего безымянного модуля.
Любые классы, которые агент организует определить загрузчиком классов начальной загрузки как члены его безымянного модуля.
Если классам агента необходимо связываться с классами платформы (или других модулей), не входящими в начальный слой, приложение, возможно, потребуется запустить так, чтобы эти модули оказались в начальном слое. Например, в реализации JDK параметр командной строки --add-modules можно использовать для добавления модулей в набор корневых модулей, разрешаемых при запуске.
Вспомогательные классы, загрузку которых агент организует с помощью загрузчика классов начальной загрузки (посредством appendToBootstrapClassLoaderSearch или указанного ниже атрибута Boot-Class-Path), должны связываться только с классами, определенными загрузчиком классов начальной загрузки. Нет гарантии, что все классы платформы могут быть определены загрузчиком классов начальной загрузки.
Если настроен пользовательский системный загрузчик классов (с помощью системного свойства java.system.class.loader, как указано в методе getSystemClassLoader), он должен определять метод appendToClassPathForInstrumentation, как указано в appendToSystemClassLoaderSearch. Иными словами, пользовательский системный загрузчик классов должен поддерживать механизм добавления JAR-файла агента в путь поиска системного загрузчика классов.
Атрибуты манифеста JAR-файла
Для Java-агентов определены следующие атрибуты в основном разделе манифеста JAR-файла приложения или агента:
Launcher-Agent-Class- Если реализация поддерживает механизм запуска приложения в исполняемом JAR-файле, этот атрибут, если он присутствует, указывает двоичное имя класса агента, упакованного вместе с приложением. Агент запускается вызовом метода
agentmainкласса агента. Он вызывается до вызова методаmainприложения.Premain-Class- Если при запуске JVM указан JAR-файл агента, этот атрибут задает двоичное имя класса агента в JAR-файле. Агент запускается вызовом метода
premainкласса агента. Он вызывается до вызова методаmainприложения. Если атрибут отсутствует, JVM завершит работу.Agent-Class- Если реализация поддерживает механизм запуска агента через некоторое время после запуска JVM, этот атрибут задает двоичное имя класса Java-агента в JAR-файле агента. Агент запускается вызовом метода
agentmainкласса агента. Этот атрибут обязателен; если он отсутствует, агент запущен не будет.Boot-Class-Path- Список путей для поиска загрузчиком классов начальной загрузки. Пути указывают каталоги или библиотеки (на многих платформах обычно называемые JAR- или zip-библиотеками). Загрузчик классов начальной загрузки ищет по этим путям после того, как не удалось найти класс с помощью механизмов, специфичных для платформы. Поиск выполняется в порядке перечисления путей. Пути в списке разделяются одним или несколькими пробелами. Синтаксис пути соответствует синтаксису компонента пути иерархического 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 игнорируется).
Инструментирование кода в модулях
Чтобы помочь агентам, размещающим вспомогательные классы в пути поиска загрузчика классов начальной загрузки или в пути поиска загрузчика классов, загружающего основной класс агента, виртуальная машина Java обеспечивает чтение безымянных модулей обоих загрузчиков модулем преобразуемых классов.
- С версии:
- 1.5
| Класс | Описание |
|---|---|
| ClassDefinition | Этот класс служит блоком параметров для метода Instrumentation.redefineClasses. |
| ClassFileTransformer | Преобразователь файлов классов. |
| IllegalClassFormatException | Выбрасывается реализацией ClassFileTransformer.transform, если ее входные параметры недопустимы. |
| Instrumentation | Этот класс предоставляет службы, необходимые для инструментирования кода на языке программирования Java. |
| UnmodifiableClassException | Выбрасывается реализацией Instrumentation.redefineClasses, если один из указанных классов невозможно изменить. |
| UnmodifiableModuleException | Выбрасывается, чтобы указать, что модуль невозможно изменить. |
© 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/package-summary.html