gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 02:35:52 28 4
gpt4 key购买 nike

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

让我解释一下我所知道的,然后提出问题......

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

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

但是,据我目前所知,一旦虚拟机加载了该类,它就会将其存储在某个共享空间中,因此不必再次加载它。

我遇到的问题是,有时卸载和重新加载新类不起作用。旧类(class)仍然存在。按理说,如果我卸载一个类加载器(即使类加载器无法访问)并且该类加载器中的某个类当前正在使用(存在该类型的对象),则无法卸载该类。

这是真的吗?实践中似乎确实如此。

如果是这样,我如何成功卸载类加载器无法访问时正在使用的类。例如,我可以在每个类上放置一个弱引用,以便我可以检测到类何时无法访问,并在类无法访问时采取行动吗? (但不确定我可以采取什么行动)。

更新响应@Kayaman

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

结论

@Kayamam 非常感谢您的咨询。这非常有帮助。这在一定程度上规范了我的想法。结论是,无论我使用什么技术,在虚拟机的现有方式下,您都无法重新加载当前存在强可达对象的类。对于我的一些重新加载,我可以控制这些对象,因为我可以在卸载和重新加载之前使它们无法访问,但对于其他类,我不能这样做......这就是我的问题所在。我需要做的是围住我希望重新加载的类的对象,以便在重新加载这些对象的类时可以暂停使用它们的进程。

最佳答案

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

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

因此,要完全重新加载,您需要删除旧实例并删除类加载器。这也避免了出现有关 MyClass != MyClass 的神秘异常的情况。

WeakReference(或 PhantomReference 在这里可能会更好)可以让您注意到现有对象何时被收集,您只需要确保正在跟踪它们全部。

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

通过快速谷歌搜索,我发现了这个 http://docs.spring.io/spring-boot/docs/current/reference/html/howto-hotswapping.html其中提到 Spring Loaded显然可以进行类重新加载等等。

关于java - 当这些类可能正在使用时,如何成功卸载这些类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43089729/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com