【发布时间】:2009-08-14 10:46:45
【问题描述】:
是否可以在虚拟机从同一个 VM 中启动后插入 javaagent?
假设我们在 jar myagent.jar 中有一个代理,其中包含适当的元数据设置和一个已经实现的 agentmain 方法。现在用户程序调用 API 调用,这应该会导致插入代理,以便它可以重新定义类。
能做到吗?怎么做?
【问题讨论】:
标签: java javaagents
是否可以在虚拟机从同一个 VM 中启动后插入 javaagent?
假设我们在 jar myagent.jar 中有一个代理,其中包含适当的元数据设置和一个已经实现的 agentmain 方法。现在用户程序调用 API 调用,这应该会导致插入代理,以便它可以重新定义类。
能做到吗?怎么做?
【问题讨论】:
标签: java javaagents
【讨论】:
是的,您只需将 JVM 进程 ID 传递给 VirtualMachine.attach(String pid) 方法,然后加载代理 jar。 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 中执行此操作,请参阅 package documentation 章节“在 VM 启动后启动代理”
编辑:也许在 Java 5 中已经有可能了,只是 javadocs 没有明确提到它
【讨论】:
遇到同样的问题,我找到了一个更全面的解决方案,from the ByteBuddy library。
ByteBuddy 彻底尝试动态加载其 java 代理:
在当前运行的 Java 虚拟机上安装代理。不幸的是,这并不总是有效。支持 Java 代理的运行时安装:
JVM 版本 9+:对于至少版本 9 的 Java VM,附件 API 已移至模块中,并且如果 Byte Buddy 可以使用 {@code jdk.attach} 模块,则可以进行运行时安装这通常仅适用于附带 JDK 的 VM。 OpenJDK / Oracle JDK / IBM J9 版本 8-:HotSpot 的安装仅在与 JDK 捆绑时才有可能,并且需要与 VM 捆绑在一起的 {@code tools.jar},这通常仅适用于JVM 的 JDK 版本。 在运行 Linux 并包含可选的 junixsocket-native-common 依赖项时,Byte Buddy 会模拟 Unix 套接字连接以附加到目标 VM。
【讨论】: