Запуск агента Java после запуска программы
Можно ли вставить javaagent после запуска виртуальной машины из той же виртуальной машины?
Допустим, например, у нас есть агент в jar myagent.jar с соответствующей настройкой метаданных и уже реализованным методом agentmain. Теперь пользовательская программа вызывает API-вызов, который должен привести к вставке агента, чтобы он мог переопределить классы.
Можно ли это сделать и как?
3 ответа
https://web.archive.org/web/20141014195801/http://dhruba.name/2010/02/07/creation-dynamic-loading-and-instrumentation-with-javaagents/ содержит отличный пример того, как писать агент, а также, как начать один на лету.
Да, вам просто нужно передать идентификатор процесса JVM в VirtualMachine.attach(String pid)
метод и загрузить агент банку. VirtualMachine
класс доступен в файле JDK_HOME/lib/tools.jar. Вот пример того, как я активирую агент во время выполнения:
public static void attachGivenAgentToThisVM(String pathToAgentJar) {
try {
String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
String pid = nameOfRunningVM.substring(0, nameOfRunningVM.indexOf('@'));
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent(pathToAgentJar, "");
vm.detach();
} catch (Exception e) {
e.printStackTrace();
}
}
Вы должны быть в состоянии сделать это в Java 6, см. Главу документации пакета "Запуск агентов после запуска виртуальной машины"
Редактировать: Возможно, это было возможно в Java 5 уже, и просто Javadocs не упомянул об этом явно
Столкнувшись с той же проблемой, я нашел гораздо более полное решение из библиотеки ByteBuddy.
ByteBuddy тщательно пытается динамически загрузить свой java-агент:
Устанавливает агент на работающую в данный момент виртуальную машину Java. К сожалению, это не всегда работает. Установка агента Java во время выполнения поддерживается для:
JVM версии 9+: для Java VM как минимум версии 9 API вложений был перемещен в модуль, и установка среды выполнения возможна, если для Byte Buddy доступен модуль {@code jdk.attach}, который обычно доступен только для виртуальных машин. поставляется с JDK. OpenJDK / Oracle JDK / IBM J9 версий 8-: установка HotSpot возможна только в комплекте с JDK и требует {@code tools.jar} в комплекте с виртуальной машиной, который обычно доступен только для JDK-версий JVM. При запуске Linux и включении дополнительной зависимости junixsocket-native-common Byte Buddy имитирует соединение сокета Unix для подключения к целевой виртуальной машине.