什么是类加载器泄漏?

问题描述 投票:0回答:3

我在谷歌中看到了如何解决类加载器泄漏的方法,但没有任何地方解释什么是类加载器泄漏?

假设我加载一个对象

Person person = new Person()
,那么Person类将由类加载器加载。Person类对象它将永远保留在元空间中(在java 8之前它将保留在permgen中),即使它是Person对象(不是person类对象) ) 不在应用程序的任何地方使用。会被认为是内存泄漏吗?

java memory-management memory-leaks classloader
3个回答
9
投票

在应用程序服务器内重新加载或重新部署应用程序时可能会发生类加载器泄漏,但重新启动整个服务器时不会发生。每次您在应用程序服务器中重新启动应用程序时,例如Tomcat,然后将创建一个新的类加载器以加载应用程序的类。同时旧的类加载器不再使用。由于对旧类加载器的所有引用都已被删除,因此它现在应该可用于垃圾回收。如果尚未删除对旧类加载器的所有引用,则无法对其进行垃圾收集,并且存在类加载器泄漏。

类加载器泄漏的一个相当常见的原因是在一个应用程序服务器内的多个应用程序之间使用共享库。如果例如这样的库持有对 Web 应用程序类加载器的静态引用,那么即使应用程序停止后,该类加载器也无法被垃圾回收。


1
投票

供以后遇到此问题的人使用。自定义 java 类加载器可以在任何 java 应用程序中使用,将类的新版本重新加载到已经运行的 jvm 中。有很多场景都需要这样做。因此,您启动您的应用程序(即jvm),然后编辑它加载的类的代码,然后使用自定义类加载器将新版本重新加载到应用程序,而无需关闭您的应用程序(jvm)。当类重新加载发挥作用时,有严格的规则。违反规则就会导致类加载器内存泄漏。您可以通过从 JDK bin 目录加载 Java VisualJVM 应用程序来监视已加载类和实例计数以及增量和堆空间的情况。最简单的方法是从应用程序本身加载 VisualJVM,并使用 PID 作为参数。


0
投票

如果不创建类加载器,就不会出现类加载器泄漏。

如果您随着时间的推移创建多个类加载器并期望旧类加载器中的所有类都被垃圾收集,则会发生类加载器泄漏。这种最常见的场景是在容器中重新加载 Web 应用程序。

类加载器的垃圾收集很棘手,因为即使您在代码中没有保存任何引用,例如在使用 ThreadLocals 时,仍然可以通过一些不明显的方式引用实例。

© www.soinside.com 2019 - 2024. All rights reserved.