【问题标题】:Starting a Java agent after program start程序启动后启动 Java 代理
【发布时间】:2009-08-14 10:46:45
【问题描述】:

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

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

能做到吗?怎么做?

【问题讨论】:

    标签: java javaagents


    【解决方案1】:

    【讨论】:

    • 这并不是一个独立的教程,真的。但对于高级 Java 开发人员来说,这是一个很好的例子。我个人认为这个例子没有问题。
    • 链接已损坏。我能够在 WayBackMachine 上找到它存档:web.archive.org/web/20141014195801/http://dhruba.name/2010/02/…
    • 该链接不再起作用。您应该已复制内容并粘贴到此处。
    • 返回链接就足够了
    • @AlanCabrera 我正在使用 jdk 1.8。我尝试过 oracle 和 openjdk,但我永远无法连接到 jvm。该尝试导致目标 jvm 中出现线程转储,并且在注入 jvm 时失败,提示 com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not respond or HotSpot VM not loaded at sun.tools.attach.LinuxVirtualMachine。 (LinuxVirtualMachine.java:106) 在 sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:63) 在 com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208) 在 Main.main (Main.java:15)
    【解决方案2】:

    是的,您只需将 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();
      }
    }                                                                                                            
    

    【讨论】:

    • 感谢您的好回答。但是当我尝试相同但出现异常时 ** com.sun.tools.attach.AgentLoadException: Agent JAR not found or no Agent-Class attribute **
    • 我怀疑这是一个依赖问题,这里如何在 maven 中解决:m.blog.csdn.net/blog/chendeng8899/8487336(“在运行时动态加载 javaagent”部分)
    • @11101101b 我使用的是 jdk 1.8。我已经尝试过 oracle 和 openjdk,但我永远无法连接到 jvm。该尝试导致目标 jvm 中出现线程转储,并且在注入 jvm 时失败,提示 com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not respond or HotSpot VM not loaded at sun.tools.attach.LinuxVirtualMachine。 (LinuxVirtualMachine.java:106) 在 sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:63) 在 com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208) 在 Main.main (Main.java:15)
    • 我在 CentOS 和 Ubuntu 上试过这个。两者都以同样的方式失败
    • 它需要tools.jar,是否值得在类路径中添加tools.jar。 (使用Java8)
    【解决方案3】:

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

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

    【讨论】:

    • 它没有指定方法调用是什么。然而,进一步研究它会 ((URLClassLoader)ClassLoader.getSystemClassLoader()).addURL(....) 添加指向 myagent.jar 的 URL 会导致调用 agentmain?
    • 这个 Java 6 是通用的还是只有 HotSpot 的?
    • @Paul:我还没有尝试过,所以我不能说它是否可以这样工作,但它似乎是合理的。但是,您必须通过反射调用 addURL,因为它受到保护。类似于: URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();类 sysclass= URLClassLoader.class;尝试 { Method method = sysclass.getDeclaredMethod("addURL",parameters);方法.setAccessible(true); method.invoke(sysloader,new Object[]{ yourURL }); }
    【解决方案4】:

    遇到同样的问题,我找到了一个更全面的解决方案,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。
  • 【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-19
      • 2017-03-07
      • 1970-01-01
      • 2017-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      相关资源
      最近更新 更多