提问者:小点点

如何在代码中动态添加Java代理jar后卸载它们?Java工具


我创建了一个 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代理罐子?
  • 是关闭/重启JVM的唯一方法吗?
  • 如果罐子留在内存中有什么影响吗?

共1个答案

匿名用户

嗯,有几件事需要考虑:

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

一些研究表明,代理将由SystemClassLoader加载,因此卸载这些类是不可能的。

VM启动后的启动代理

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

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

您想关闭该代理?提供关闭方法。

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

然后,该方法可以从插装接口中移除转换器,或者停止代理在Java VM中正在做的任何事情(释放被占用的引用/资源,以便对象被垃圾收集,诸如此类)。

如果不更具体地说明你想要实现的目标,就很难给出一个更合适的答案。