卸载Java中的类?

时间:2020-03-06 14:52:27  来源:igfitidea点击:

我有一个自定义的类加载器,以便桌面应用程序可以动态地从需要与之交谈的AppServer加载类。我们这样做是因为这样做所需的罐子数量太可笑了(如果我们想发货的话)。如果我们没有在运行时从AppServer库动态加载类,我们还将遇到版本问题。

现在,我遇到一个问题,需要与两个不同的AppServer进行交谈,发现根据我首先加载谁的类,我可能会严重损坏...是否有任何方法可以在不杀死JVM的情况下强制卸载该类?

希望这有道理

解决方案

我们可以卸载ClassLoader,但不能卸载特定的类。更具体地说,我们无法卸载不受我们控制的ClassLoader中创建的类。

如果可能的话,我建议我们使用自己的ClassLoader,以便卸载。

类加载器可能是一个棘手的问题。如果我们使用多个类加载器,并且没有清晰,严格地定义它们的交互,则尤其容易遇到问题。我认为,为了能够真正卸载我们要去的类,必须删除对要卸载的任何类(及其实例)的所有引用。

大多数需要做这种事情的人最终都使用OSGi。 OSGi确实功能强大,而且重量惊人且易于使用,

可以卸载类的唯一方法是,如果使用的类加载器是垃圾回收。这意味着对每个单个类的引用以及对类加载器的引用都需要遵循dodo的方式。

一种可能的解决方案是为每个jar文件提供一个Classloader,为每个AppServer提供一个Classloader,以将类的实际加载委托给特定的Jar类加载器。这样,我们可以为每个App服务器指向jar文件的不同版本。

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

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

并创建一个扩展Classloader的新的MultiClassloader类。此类在内部将具有JarClassloaders的数组(或者List),并且在defineClass()方法中将迭代所有内部类加载器,直到找到定义或者抛出NoClassDefFoundException为止。可以提供几个访问器方法,以将新的JarClassloaders添加到类中。网络上有一个针对MultiClassLoader的可能的实现,因此我们可能甚至不需要编写自己的实现。

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

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

是的,有多种方法可以加载类,并在以后"卸载"它们。诀窍是实现自己的类加载器,该类加载器位于高层类加载器(系统类加载器)与应用服务器的类加载器之间,并希望应用服务器的类加载器确实将类加载委托给上层加载器。

一个类由其包,名称和最初加载的类加载器定义。编写一个"代理"类加载器,这是启动JVM时首先加载的类加载器。工作流程:

  • 程序启动,此代理类加载器加载真正的"主"类。
  • 随后正常加载的每个类(即不通过可能会破坏层次结构的另一个类加载器实现)都将委派给该类加载器。
  • 代理类加载器将java.x和sun.x委托给系统类加载器(这些不能通过系统类加载器之外的任何其他类加载器加载)。
  • 对于每个可替换的类,实例化一个类加载器(该类加载器实际上将加载该类,并且不会将其委派给父类加载器),并通过此加载器。
  • 将类的包/名称存储为键,将类加载器的值存储为数据结构(即Hashmap)。
  • 每次代理类加载器收到对之前加载的类的请求时,它将从之前存储的类加载器返回该类。
  • 通过类加载器定位一个类的字节数组(或者从数据结构中"删除"键/值对)并重新加载该类以防万一,如果要更改它,就足够了。

完成后不应出现ClassCastException或者LinkageError等。

有关类加载器层次结构的更多信息(是的,这正是我们在此处实现的内容),请参阅Ted Neward撰写的"基于服务器的Java编程",该书帮助我实现了与我们想要的东西非常相似的东西。

类具有对ClassLoader实例的隐式强引用,反之亦然。它们像Java对象一样被垃圾收集。在不点击工具界面或者类似界面的情况下,我们无法删除单个类。

与以往一样,我们可能会遇到内存泄漏。任何对类或者类加载器之一的强引用都会泄漏整个事情。例如,在Sun的ThreadLocal,java.sql.DriverManager和java.beans实现中就会发生这种情况。

我编写了一个自定义的类加载器,可以从中卸载单个类而无需对类加载器进行GC。罐类装载机