在虚拟机启动后,是否有可能从同一虚拟机内插入javaagent?
例如,我们有一个名为myagent.jar的jar包代理,具有适当的元数据设置和已经实现的agentmain方法。现在用户程序调用了一个API调用,应该导致插入代理以便重新定义类。
它可行吗?如何做到?
在虚拟机启动后,是否有可能从同一虚拟机内插入javaagent?
例如,我们有一个名为myagent.jar的jar包代理,具有适当的元数据设置和已经实现的agentmain方法。现在用户程序调用了一个API调用,应该导致插入代理以便重新定义类。
它可行吗?如何做到?
是的,你只需要将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();
}
}
遇到相同的问题后,我找到了一个更全面的解决方案,来自ByteBuddy库。
ByteBuddy彻底尝试动态加载其Java代理:
安装代理程序到当前运行的Java虚拟机。不幸的是,这并不总是有效。Java代理程序的运行时安装支持以下情况: