小编典典

在java中卸载类?

all

我有一个自定义类加载器,以便桌面应用程序可以从我需要与之交谈的 AppServer
动态地开始加载类。我们这样做是因为这样做所需的罐子数量是荒谬的(如果我们想运送它们)。如果我们不在运行时从 AppServer
库动态加载类,我们也会遇到版本问题。

现在,我遇到了一个问题,我需要与两个不同的 AppServers 交谈,发现根据我首先加载的类,我可能会严重崩溃……有没有办法在不实际杀死 JVM
的情况下强制卸载类?

希望这是有道理的


阅读 217

收藏
2022-07-30

共1个答案

小编典典

可以卸载类的唯一方法是使用的类加载器是垃圾收集的。这意味着,对每个类和类加载器本身的引用都需要像渡渡鸟一样。

您的问题的一种可能的解决方案是为每个 jar 文件设置一个 Classloader,并为每个 AppServers 设置一个
Classloader,将类的实际加载委托给特定的 Jar 类加载器。这样,您可以为每个 App 服务器指向不同版本的 jar 文件。

不过,这并非微不足道。OSGi 平台努力做到这一点,因为每个包都有不同的类加载器,并且依赖关系由平台解决。也许一个好的解决方案是看看它。

如果您不想使用 OSGI,一种可能的实现可能是为每个 JAR
文件使用一个JarClassloader类的实例。

并创建一个扩展 Classloader 的新 MultiClassloader 类。这个类在内部会有一个 JarClassloader 的数组(或
List),并且在 defineClass() 方法中将遍历所有内部类加载器,直到可以找到定义,或者抛出
NoClassDefFoundException。可以提供几个访问器方法来将新的 JarClassloaders
添加到类中。MultiClassLoader 在网上有几种可能的实现,因此您甚至可能不需要编写自己的实现。

如果您为与服务器的每个连接实例化一个 MultiClassloader,原则上每个服务器都可能使用同一类的不同版本。

我在一个项目中使用了 MultiClassloader 的想法,其中包含用户定义脚本的类必须从内存中加载和卸载,并且效果很好。

2022-07-30