26

是否可以在虚拟机从同一 VM 内启动后插入 javaagent?

例如,我们在 jar myagent.jar 中有一个代理,它具有适当的元数据设置和一个已经实现的 agentmain 方法。现在用户程序调用一个 API 调用,这应该会导致代理的插入,以便它可以重新定义类。

可以做到吗?怎么做?

4

4 回答 4

20

https://web.archive.org/web/20141014195801/http://dhruba.name/2010/02/07/creation-dynamic-loading-and-instrumentation-with-javaagents/有一个很好的例子来说明如何编写代理以及如何即时启动代理。

于 2010-12-18T04:04:05.093 回答
15

是的,您只需将 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();
  }
}                                                                                                            
于 2014-10-30T20:24:27.410 回答
4

您应该能够在 Java 6 中执行此操作,请参阅包文档章节“在 VM 启动后启动代理”

编辑:也许在 Java 5 中已经有可能了,只是 javadocs 没有明确提到它

于 2009-08-14T11:01:55.193 回答
0

遇到同样的问题后,我从 ByteBuddy 库中找到了更全面的解决方案。

ByteBuddy 彻底尝试动态加载其 java 代理:

在当前运行的 Java 虚拟机上安装代理。不幸的是,这并不总是有效。支持 Java 代理的运行时安装:

  • JVM 版本 9+:对于至少版本 9 的 Java VM,附件 API 已移动到一个模块中,如果 {@code jdk.attach} 模块可用于 Byte Buddy,则可以进行运行时安装,该模块通常仅适用于 VM附带 JDK。
  • OpenJDK / Oracle JDK / IBM J9 版本 8-:HotSpot 的安装只有在与 JDK 捆绑时才可能,并且需要与 VM 捆绑的 {@code tools.jar},这通常仅适用于 JVM 的 JDK 版本。
  • 在运行 Linux 并包含可选的junixsocket-native-common依赖项时,Byte Buddy 模拟 Unix 套接字连接以附加到目标 VM。
  • 于 2020-09-02T01:33:49.653 回答