我有一个java代理,它测量字节码。我正在使用Java6中的attach apis,以允许用户使用我的java代理动态加载代理和插入和释放代码。我使用Boot-Class-Path清单属性来确保我的javagent类在引导类路径中,这样我的用户就可以插入ArrayList等类。
然而,版本化带来了问题。假设用户动态附加我的代理的版本1。现在,自从他附加了我的代理的版本1之后,他的应用服务器就再也没有关闭过,所以版本1的类仍然会被加载。
我需要一些方法,这样当我的客户端javaagent版本2时,版本1就会被卸载。
我知道一种方法是为我的javaagent的类编写一个客户类加载器,并将类加载器引用设置为null。然而,在这种情况下,我将无法在引导类路径中插入类,因为我的类加载器将位于引导类加载器的层次结构的下面,因此我的用户不能插入像ArrayList这样的类,因为如果我在ArrayList的方法中向代理的一个类方法添加调用,那么引导类加载器将无法看到它们。
那么,有没有办法解决引导类路径问题,同时仍然卸载以前代理的类呢?
发布于 2009-08-12 17:04:07
我不是这个话题的专家,但似乎不直接支持这种卸载到替换的方式。
但是你需要卸载-替换这个类吗?
您是否可以创建一个与外部世界对话的永不改变的类,在这个类中您可以在内部引入一个版本控制系统?
例如,您创建了一个类MyToolAgent,它有一个静态字符串,其中包含要使用的ToolAgentImplementation的类名。当您第一次发布时,它被设置为使用ToolAgentImplementation1_0。当您升级到2.0版时,需要部署一个名为ToolAgentImplmenetation2_0的附加类,并更新MyToolAgent类以加载和使用它。您永远不会卸载1.0版,但您确实会停止使用它。您在这里确实浪费了一些内存,但您实现了版本升级。
我不知道这在您的情况下是否可行,但一般来说,JVM似乎不支持直接换入新版本,但您应该能够以某种方式隐藏这一点。
发布于 2009-08-13 20:19:07
我不确定这是否可行,但它可能会给你一些选择...
添加一个新的代理(安装程序代理),而不是尝试重新加载当前代理(让我们称之为工具代理)。安装程序代理只有一个功能:使用RedefineClasses()替换原始的工具代理类。
如果使用版本号命名安装程序代理并将其作为类名(MyToolInstallerV1)的一部分,则可以继续加载更新工具代理的新安装程序。如果大小成了问题,也许安装程序代理可以查找以前的安装程序,并将它们的类替换为一个小的无操作存根。
发布于 2009-08-17 11:34:31
到目前为止,我还没有安装任何工具,但我只是在使用java.util.ServiceLoader,并实现了某种插件架构,使用URLClassLoader的方法实现了动态JAR加载-卸载。
我不知道“指令插入”可以以这种方式改变,但是版本控制和动态加载-卸载问题可以被追踪到,而且测试它真的很快,因为困难的事情是由ServiceLoader完成的(只需遵循tiny /META-INF/services/XXX规范),您已经准备好了:)
致以问候。
https://stackoverflow.com/questions/1248061
复制相似问题