Javaagent类卸载

时间:2009-08-08 05:39:46

标签: java classloader javaagents

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

然而问题出在版本控制上。 让我们说用户动态地附加我的代理的版本1。 然后我给了他第2版。既然他的应用服务器从未关闭,因为他附加了我的代理的版本1,版本1类仍然加载。

我需要某种方式,当我的客户端版本2的javaagent,版本1被卸载。

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

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

4 个答案:

答案 0 :(得分:1)

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

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

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

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

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

答案 1 :(得分:0)

我不确定这会起作用,但它可能会给你一些选择......

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

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

答案 2 :(得分:0)

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

我不知道“仪器”可以通过这种方式改变,但可以跟踪版本控制和动态加载 - 卸载问题,并且测试它真的很快,因为硬件由ServiceLoader完成(只是按照tiny / META-INF / services / XXX规范)准备就绪:)

问候。

答案 3 :(得分:0)

OSGI的完美用例。不确定你是否可以将你的代理作为一个包插入。