Java 当类可能正在使用时,如何成功卸载这些类?

Java 当类可能正在使用时,如何成功卸载这些类?,java,classloader,dynamic-class-loaders,Java,Classloader,Dynamic Class Loaders,我在应用程序中构建了重新加载类的功能。但是,我需要澄清类加载器的行为 让我解释我所知道的,然后问问题 我要做的是提供一个特殊的jar,它由一个自定义类加载器加载。然后在jar的引导过程中,创建了一堆Springbean,实现某些接口的Springbean被注册以供中央应用程序使用 现在,我在应用程序中启动一个使用这些新类的进程。我可以成功地卸载“jar”,更改jar中的类并重新加载,然后得到更改。按照类加载器的说法,卸载意味着使加载类的类加载器不可访问-这会导致该类加载器加载的任何类不可访问,从

我在应用程序中构建了重新加载类的功能。但是,我需要澄清类加载器的行为

让我解释我所知道的,然后问问题

我要做的是提供一个特殊的jar,它由一个自定义类加载器加载。然后在jar的引导过程中,创建了一堆Springbean,实现某些接口的Springbean被注册以供中央应用程序使用

现在,我在应用程序中启动一个使用这些新类的进程。我可以成功地卸载“jar”,更改jar中的类并重新加载,然后得到更改。按照类加载器的说法,卸载意味着使加载类的类加载器不可访问-这会导致该类加载器加载的任何类不可访问,从而有效地卸载


然而,据我所知,一旦虚拟机加载了类,它就会将其存储在某个共享空间中,这样就不必再次加载

我遇到的问题是,有时新类的卸载和重新加载不起作用。旧阶级仍然存在。很显然,如果我卸载一个类加载器(即,使该类加载器不可访问),并且该类加载器中的一个类当前正在使用(存在该类型的对象),那么该类将无法卸载

这是真的吗?这在实践中似乎是正确的

如果是这样,我如何成功卸载在类装入器无法访问时正在使用的类。例如,我是否可以在每个类上放置一个弱引用,这样我就可以检测该类何时不可访问,并在该类不可访问时采取行动?(不知道我能采取什么行动)

针对@Kayaman更新

我的用例是,我拥有核心应用程序,然后根据客户的需求,我可以加载实现核心应用程序中已知接口的不同类(以便可以访问它们)。然后核心应用程序启动使用这些类的各种进程。这样做的最大优点是,我可以更新这些插件类,而无需进行大规模的重新部署,而且每个客户都不需要这些插件类中的每一个。当我想加载其中一个的新版本并且当前版本正在使用时,问题就出现了。有点道理,这是不可能的

结论


@非常感谢您的咨询。这很有帮助。这在某种程度上把我的想法编成了法典。结论是,无论我使用什么技术,您都无法以VM的方式重新加载当前具有强可访问对象的类。对于我的一些重载,我可以控制这些对象,因为我可以在卸载和重载之前使它们不可访问,但对于其他类,我不能这样做。。。这就是我的问题所在。我需要做的是对我希望重新加载的类的对象进行隔离,以便在我重新加载这些对象的类时,可以暂停使用它们的进程

正如您所说,为了卸载类,您需要去掉类加载器。例如,
URLClassLoader
可用于加载类,然后清空引用以使其符合GC的条件,从而卸载所加载的类

但是,所有类都知道哪个类加载器加载了它们。这意味着,如果您使用了类的实例,那么它们将引用
,该类引用了
类加载器
,并将阻止收集该类和卸载类。这是可以理解的,因为拥有一个没有类的对象将是一个非常有趣的情况

因此,对于完全重新加载,您需要去掉旧实例和类加载器。这也避免了出现关于
MyClass!=MyClass

WeakReference
(或者
PhantomReference
在这里可能会更好)可以让您注意到收集到现有对象时,您只需确保跟踪所有对象

Spring增加了这里的复杂性,因此我强烈建议花一些时间想象这种方法是不可能的,看看Spring是否有一些东西可以用来满足您的业务需求。毕竟,它本身做了大量的类加载,因此您可能正在以一种不太清晰的方式重新发明轮子


通过快速谷歌搜索,我发现了这一点,其中提到了一些明显可以重新加载类的东西。

“一旦虚拟机加载了类,它就会将其存储在某个共享空间”——我想你指的是Java 8的元空间或Java 7(及以下)的PermGen空间,不是吗?插件体系结构是一个相当古老的发明。正如我所说,您可以加载一个新版本,但旧版本在不再使用之前不会被卸载(但这只是意味着在某一点上,在旧版本“完成”之前,您将同时使用这两个版本)。我下面的链接应该至少提供了一个以Spring方式实现的起点。我不能使用弱引用来计算这些类何时不再使用。在类装入器变得不可访问之后,这尤其可能。换句话说,我会使类加载器不可访问,然后在等待该类加载器加载的所有类不可访问时暂停,因为这意味着它们不再使用,我可以重新加载它们。虽然有可能是对类的引用使类加载器保持不变。。。更好的方法可能是将重点放在类加载器上,因为肯定是正在使用的类保持了类加载器。因此,如果一个类装入器对类装入器进行弱引用,那么当它的所有类都不可访问时,我可以监视它,从而能够在该类装入器中重新装入类。是的,我想的是错误的方法。对hav来说真的没有意义