Java代理类卸载

3
我有一个Java代理程序,它可以对字节码进行检测。 我正在使用Java 6中的附加API允许用户动态加载代理程序,并使用我的Java代理程序来检测和去除代码。 我使用Boot-Class-Path清单属性来确保我的Java代理程序类在引导类路径中,以便我的用户可以检测像ArrayList等类。
但是问题出现在版本控制上。 假设用户动态附加了我的代理程序的第1个版本。 然后我给他第2个版本。现在由于他的应用服务器自从安装第1个版本的代理程序以来从未关闭过,所以第1个版本的类仍在加载中。
我需要一种方法,使得当客户端安装第2个版本的Java代理程序时,第1个版本会被卸载。
我知道一种方法是为我的Java代理程序的类编写一个自定义类装入器,并将类装入器引用设置为null。 然而,在这种情况下,我将无法检测引导类路径中的类,因为我的类装入器将位于引导类装入器的层次结构下面,因此我的用户无法检测像ArrayList这样的类,因为如果我在ArrayList的方法中添加一个调用到我的代理程序类的方法,则引导类装入器将无法看到它们。
那么有没有办法解决引导类路径问题并仍然卸载先前代理程序的类呢?

1
你可能想要看一下JavaRebel(http://www.zeroturnaround.com/javarebel/),它是你正在尝试做的事情的商业实现。它可能会让你了解什么是可能的,什么是不可能的。 - skaffman
4个回答

1

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

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

你能否创建一个永远不会改变的类,外部世界与之通信,在其中你内部实现一个版本控制系统?

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

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


0

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


0

目前我还没有进行任何仪器化,但我正在尝试使用java.util.ServiceLoader并实现了一种插件架构,采用动态JAR加载和卸载的URLClassLoader方法。

我不知道“仪器化”可以这样改变,但版本控制和动态加载/卸载问题可以被解决,而且测试速度非常快,因为ServiceLoader已经完成了困难的部分(只需遵循微小的/META-INF/services/XXX规范),你就准备好了 :)

敬礼。


0

我不确定这个方法是否有效,但它可能会给您提供一些选项...

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接