我有一个自定义的类加载器,以便桌面应用程序可以动态地从需要与之交谈的AppServer加载类。我们这样做是因为这样做所需的罐子数量太可笑了(如果我们想发货的话)。如果我们没有在运行时从AppServer库动态加载类,我们还将遇到版本问题。
现在,我遇到一个问题,需要与两个不同的AppServer进行交谈,发现根据我首先加载的类,我可能会严重损坏...是否有任何方法可以在不杀死JVM的情况下强制卸载该类?
希望这有意义
我有一个自定义的类加载器,以便桌面应用程序可以动态地从需要与之交谈的AppServer加载类。我们这样做是因为这样做所需的罐子数量太可笑了(如果我们想发货的话)。如果我们没有在运行时从AppServer库动态加载类,我们还将遇到版本问题。
现在,我遇到一个问题,需要与两个不同的AppServer进行交谈,发现根据我首先加载的类,我可能会严重损坏...是否有任何方法可以在不杀死JVM的情况下强制卸载该类?
希望这有意义
Answers:
可以卸载类的唯一方法是,如果使用的类加载器是垃圾回收。这意味着,对每个单个类的引用以及对类加载器的引用都需要遵循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
在系统类加载器(这些不得通过任何其他的类加载器不是系统类加载器加载)。完成后不应出现ClassCastException或LinkageError等。
有关类加载器层次结构的更多信息(是的,这正是您在此处实现的内容;-)请参阅Ted Neward撰写的“基于服务器的Java编程” -该书帮助我实现了与您想要的东西非常相似的东西。
ClassLoader
每个班级只有一个太多,ClassLoader
每个JAR 一个都有意义。可以更具体地说明如何在建议的模式中强制类上传吗?例如,我如何保证ClassLoaderB加载的实例不会引用ClassLoaderA加载的类的实例?
您可以卸载ClassLoader,但不能卸载特定的类。更具体地说,您不能卸载不受您控制的ClassLoader中创建的类。
如果可能的话,我建议您使用自己的ClassLoader,以便卸载。