【问题标题】:Javaagent class unloadingJavaagent 类卸载
【发布时间】:2009-08-08 05:39:45
【问题描述】:

我有一个检测字节码的 java 代理。 我正在使用 java 6 中的附加 api 来允许用户使用我的 java 代理动态加载代理和仪器并取消仪器代码。 我正在使用 Boot-Class-Path 清单属性来确保我的 javagent 类位于引导类路径中,以便我的用户可以检测 ArrayList 等类。

但是问题在于版本控制。 假设用户动态附加了我的代理的版本 1。 然后我给了他第 2 版。现在,自从他附加了我的代理的第 1 版后,他的应用服务器从未关闭过,所以第 1 版的类仍在加载。

我需要一些方法,以便当我的客户端版本 2 的 javaagent 被卸载时,版本 1 被卸载。

我知道一种方法是为我的 javaagent 的类编写一个客户类加载器,并将类加载器引用设置为 null。 但是,在这种情况下,我将无法在引导类路径中检测类,因为我的类加载器将位于引导类加载器的层次结构中,因此我的用户无法检测像 ArrayList 这样的类,因为如果我在 ArrayList 的方法中添加一个调用到我的一个代理类的方法,引导类加载器将无法看到它们。

那么有什么办法可以解决引导类路径问题,并且仍然卸载之前代理的类?

【问题讨论】:

  • 您可能想看看 JavaRebel (zeroturnaround.com/javarebel),它是您正在尝试做的事情的商业实现。它可能会让你知道什么是可能的,什么是不可能的。

标签: java classloader javaagents


【解决方案1】:

我不是这方面的专家,但似乎不直接支持这种卸载替换。

但是你需要卸载替换类吗?

您能否改为创建一个与外部世界对话的永不改变的类,您可以在其中内部实现版本控制系统?

例如,您创建的 MyToolAgent 类有一个静态字符串,其中包含要使用的 ToolAgentImplementation 的类名。首次发布时,它设置为使用 ToolAgentImplementation1_0。当您升级到 2.0 版时,您部署了一个名为 ToolAgentImplmenetation2_0 的附加类,并更新了 MyToolAgent 类以加载和使用它。您永远不会卸载 1.0 版,但您确实停止使用它。这里确实浪费了一些内存,但是实现了版本升级。

我不知道这在您的情况下是否可行,但总的来说 JVM 似乎不支持直接交换新版本,但您应该能够以某种方式隐藏它。

【讨论】:

    【解决方案2】:

    我不确定这是否可行,但它可能会为您提供一些选择...

    不要尝试重新加载当前代理(我们称之为工具代理),而是添加一个新代理(安装程序代理)。安装程序代理只有 1 个功能:使用 RedefineClasses() 替换原来的工具代理类。

    如果您使用版本号作为类名 (MyToolInstallerV1) 的一部分命名安装程序代理,您可以继续加载更新工具代理的新安装程序。如果大小成为问题,也许安装代理可以寻找以前的安装程序并用一个小的无操作存根替换他们的类。

    【讨论】:

      【解决方案3】:

      我现在还没有检测任何东西,但我只是在玩java.util.ServiceLoader 并实现了某种插件架构,通过 URLClassLoader 的方法动态 JAR 加载-卸载。

      我不知道“仪器”可以通过这种方式进行更改,但是可以跟踪版本控制和动态加载-卸载问题,并且测试它真的很快,因为困难的事情是由 ServiceLoader 完成的(只是遵循小 /META-INF/services/XXX 规范),你就准备好了:)

      问候。

      【讨论】:

        【解决方案4】:

        OSGI 的完美用例。不确定您是否可以将代理作为捆绑包插入。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-09-14
          • 2012-02-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多