Java 自定义类加载器是否会导致内存泄漏?
Java 自定义类加载器是否会导致内存泄漏?,java,classloader,Java,Classloader,ClassLoaders存储在永久生成内存中。正如java热点中的java内存管理白皮书所述™ 虚拟机,永久性的一代内存肯定会被垃圾回收。那么,定制Classloader是否仍然会导致内存泄漏?如果是的话,那它是怎么发生的呢 更新 在@Marko Topolnik和@Prunge的帮助下,我澄清了我的疑问。下面是关于类加载器和内存泄漏的要点: 自定义ClassLoaders未存储在Perm生成中 如果ClassLoder超出范围,但无论我们是否将ClassLoader对象设置为null,自定义C
ClassLoader
s存储在永久生成内存中。正如java热点中的java内存管理白皮书所述™ 虚拟机,永久性的一代内存肯定会被垃圾回收。那么,定制Classloader
是否仍然会导致内存泄漏?如果是的话,那它是怎么发生的呢
更新
在@Marko Topolnik和@Prunge的帮助下,我澄清了我的疑问。下面是关于类加载器和内存泄漏的要点:
ClassLoader
s未存储在Perm生成中ClassLoder
超出范围,但无论我们是否将ClassLoader
对象设置为null
,自定义ClassLoader
都会导致内存泄漏,但应用程序仍会引用它加载的类ClassLoader
对象,那么我们应该确保从加载的类开发的对象的所有引用都应该是null
ClassLoader
加载的任何类都不符合GC
的条件,那么ClassLoader将不会被GCed
自定义类加载器本身不会导致内存泄漏。如果未正确使用它们加载的类,则可能发生泄漏 类和类加载器可以正常地进行垃圾收集-这可以通过
-Xnoclassgc
命令行选项关闭,但用户必须明确地执行此操作。类加载器具有对其所有类的引用,因此只有当所有类不再被引用时,才能对类加载器进行垃圾收集
当从自定义类加载器加载的类或这些类的实例仍在应用程序中引用时,可能会发生泄漏
一个常见的例子是Java EE web容器,如Tomcat:
让我们假设容器中的每个webapp都有自己的类加载器。卸载webapp时,容器会删除该应用程序,所有类(包括已编译的JSP)都不应再被引用,迟早会通过垃圾收集清理这些类和类加载器。但是webapp可能已经在DriverManager
中注册了一个数据库驱动程序,或者使用了一些(很可能是通过一个流行的第三方库间接进行反射)来缓存bean元数据,因此webapp类加载器中的类在webapp取消部署后仍然有效,仍然被webapp的类加载器未加载的其他对象强烈引用
Tomcat有一个很好的解决方案,以及它是如何在他们周围工作的
但是,如果自定义类加载器写入正确,则不会导致泄漏。类加载器未存储在PermGen空间中。类数据存储在那里,它只与进行加载的类加载器间接相关:类加载器持有对其加载的每个类的引用 提供了很好的信息,除了一件事:在PermGen空间中分配类加载器是错误的。类加载器只是普通的Java类,PermGen只包含特殊的材料,而不是常规的对象数据。例如,它保存所有静态类变量和方法的可执行代码
可以找到有关热点内存布局和垃圾收集详细信息的大量资源。您有什么证据证明内存泄漏?类加载器不存储在permGen中。类数据存储在那里,完全独立于进行加载的类加载器。关于类加载器的陈述是不正确的。它们只是普通的Java类。PermGen包含的特殊材料不是常规的对象数据。是的,您在所有方面都是正确的,您已经很好地总结了为什么很容易导致类加载器泄漏。感谢您的清晰而漂亮的解释。。因此,让我回忆一下我在这个线程中所知道的一切:1)Custom
ClassLoader
s未存储在永久性的第二代中2)CustomClassLoader
s可能会导致内存泄漏,如果ClassLoder超出范围,但无论我是否设置了ClassLoader
对象为null
。3) 如果我们不需要一个给定的类加载器对象,我们应该确保从加载的类开发的对象的所有引用都应该是null
。如果我哪里做错了,请纠正我。。