3

我创建了一个 java 代理 jar 文件(在命令行上完美运行)。接下来,我想将此代理附加到 j2ee 服务器中正在运行的 JVM。所以我使用了代码:

public static void loadAgent() {   

    System.out.println("dynamically loading javaagent");
    String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
    int p = nameOfRunningVM.indexOf('@');
    String pid = nameOfRunningVM.substring(0, p);

    try {
        VirtualMachine vm = VirtualMachine.attach(pid);
        String jarFilePath = vm.getSystemProperties().getProperty("java.home")+File.separator+"lib"+File.separator+"test-agent-7.jar";            
        vm.loadAgent(jarFilePath, "");
        vm.detach();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

编辑:这现在可以工作了,我可以看到 Transformer 被调用了。我还可以移除变压器并能够调试变压器。

我的问题是:

  • 完成后如何卸载此 java 代理 jar?
  • 是关闭/重新启动 JVM 的唯一方法吗?
  • 如果罐子留在内存中会有什么影响吗?
4

1 回答 1

2

嗯,有几件事需要考虑:

如果加载代理,则加载类。只要相关的类加载器在 Java VM 的内存中,相关的类就会保持加载状态。我认为你不能轻易地防止/规避。但这应该只是您通过加载代理所产生的一小部分内存开销。

一些研究表明,代理将由 SystemClassLoader 加载,因此无法卸载这些类。

虚拟机启动后启动代理

实现可以提供一种机制来在 VM 启动后的某个时间启动代理。关于如何启动的细节是特定于实现的,但通常应用程序已经启动并且它的 main 方法已经被调用。如果实现支持在 VM 启动后启动代理,则适用以下情况:代理 JAR 的清单必须包含属性 Agent-Class。该属性的值是代理类的名称。代理类必须实现公共静态 agentmain 方法。系统类加载器 (ClassLoader.getSystemClassLoader) 必须支持将代理 JAR 文件添加到系统类路径的机制。 链接到源

但是,您可以影响的是代理正在做什么。

你想关闭那个代理吗?提供关闭方法。

如果你想从外部停止代理,这个代理可以提供一个 JMXBean 来关闭代理。

然后,此方法可以从 Instrumentation 接口中删除转换器或停止代理在 Java VM 中执行的任何其他操作(释放所持有的引用/资源,以便对对象进行垃圾收集,诸如此类)。

如果没有更具体地说明您想要实现的目标,很难给出更合适的答案。

于 2013-12-12T13:26:10.517 回答