我有一个检测字节码的 Java 代理。 我在 java 6 中使用附加 api,以允许用户使用我的 java 代理动态加载代理和工具以及取消工具代码。 我正在使用 Boot-Class-Path list 属性来确保我的 javagent 类位于引导类路径中,以便我的用户可以检测 ArrayList 等类。
但是问题来自版本控制。 假设用户动态附加了我的代理的版本 1。 然后我给了他第 2 版。现在,由于他的应用程序服务器自从他附加了我的代理的第 1 版以来从未关闭过,因此仍然加载了第 1 版类。
我需要一些方法,当我的 javaagent 客户端版本 2 被卸载时,版本 1 被卸载。
我知道一种方法是为我的 javaagent 类编写一个客户类加载器,并将类加载器引用设置为 null。 但是,在那种情况下,我将无法在引导类路径中检测类,因为我的类加载器将位于引导类加载器的层次结构下方,因此我的用户无法检测像 ArrayList 这样的类,因为如果我在 ArrayList 的方法中添加一个调用到我的其中一个代理类的方法引导类加载器将无法看到它们。
那么有什么办法可以解决boot classpath的问题,并且仍然卸载之前agent的类吗?
最佳答案
我不是这方面的专家,但似乎不直接支持这种卸载到替换。
但是你需要卸载-替换类吗?
您能否改为创建一个与外部世界对话的永不改变的类,您可以在其中实现版本控制系统?
例如,您创建类 MyToolAgent,它有一个静态字符串,其中包含要使用的 ToolAgentImplementation 的类名。首次发布时,它设置为使用 ToolAgentImplementation1_0。当您升级到 2.0 版时,您部署了一个名为 ToolAgentImplmenetation2_0 的附加类,并更新了 MyToolAgent 类以加载和使用它。您永远不会卸载 1.0 版,但您会停止使用它。你在这里确实浪费了一些内存,但是你实现了版本升级。
我不知道这在你的情况下是否可行,但一般来说,JVM 似乎不支持直接交换新版本,但你应该能够以某种方式隐藏它。
关于Javaagent类卸载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1248061/