程序启动后启动Java代理程序

时间:2009-08-14 10:46:45

标签: java javaagents

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

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

能做到吗?怎么做?

4 个答案:

答案 0 :(得分:20)

答案 1 :(得分:14)

是的,您只需将JVM进程ID传递给VirtualMachine.attach(String pid)方法,然后加载代理jar。 JDK_HOME / lib / tools.jar文件中提供了VirtualMachine类。以下是我在运行时如何激活代理的示例:

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();
  }
}                                                                                                            

答案 2 :(得分:4)

您应该可以在Java 6中执行此操作,请参阅package documentation章节“VM启动后启动代理”

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

答案 3 :(得分:0)

遇到相同的问题,我发现了一个更加全面的解决方案from the ByteBuddy library

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

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

  • JVM版本9 + :对于版本至少为9的Java VM,附件API已移至模块中,并且如果{@code jdk.attach}模块可用,则可以进行运行时安装到Byte Buddy,通常仅适用于JDK附带的VM。
  • OpenJDK / Oracle JDK / IBM J9版本8-:仅当与JDK捆绑在一起时才可以安装HotSpot,并且需要与VM捆绑在一起的{@code tools.jar}仅适用于JVM的JDK版本。
  • 运行Linux并包括可选的 junixsocket-native-common 依赖项时,Byte Buddy仿真Unix套接字连接以附加到目标VM。