3

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

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

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

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

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

4

4 回答 4

1

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

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

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

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

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

于 2009-08-12T17:04:07.207 回答
0

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

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

问候。

于 2009-08-17T11:34:31.230 回答
0

我不确定这会奏效,但它可能会给你一些选择......

与其尝试重新加载当前代理(我们称其为工具代理),不如添加一个新代理(安装程序代理)。安装程序代理将只有 1 个功能:使用 RedefineClasses() 替换原始工具代理类。

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

于 2009-08-13T20:19:06.827 回答
0

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

于 2011-01-27T09:37:12.003 回答