Custom ClassLoader会导致内存泄漏吗?

时间:2013-07-27 13:25:48

标签: java classloader

ClassLoader存储在永久代内存中。正如Java HotSpot™虚拟机中的内存管理白皮书所述,永久生成内存肯定是垃圾回收。那么,自定义Classloader是否仍会导致内存泄漏?如果是,那怎么会发生呢?

更新

在@Marko Topolnik和@Prunge的帮助下,我明白了我的怀疑。以下几点是关于ClassLoaders和Memory Leaks:

  1. 自定义ClassLoader未存储在Perm生成中。
  2. 如果ClassLoader超出范围,自定义ClassLoder可能会导致内存泄漏,但无论我们是否将ClassLoader对象设置为null
  3. 如果我们不需要给定的ClassLoader对象,那么我们应该确保从加载的类开发的对象的所有引用都应该是null
  4. 如果ClassLoader加载的任何类不符合GC的条件,那么ClassLoader将不会是GCed

2 个答案:

答案 0 :(得分:3)

自定义类加载器本身不会导致内存泄漏。如果他们加载的类未正确使用,则可能发生泄漏。

类和类加载器可以正常进行垃圾回收 - 可以使用-Xnoclassgc命令行选项关闭它,但用户必须明确地执行此操作。类加载器引用了它们的所有类,因此如果不再引用所有类,则只能对类加载器进行垃圾回收。

当从应用程序中引用从自定义类加载器加载的这些类的类或实例时,可能会发生泄漏。

一个常见的例子是Java EE Web容器,例如Tomcat:

假设容器中的每个webapp都有自己的类加载器。卸载webapp时,容器会删除应用程序,并且不再引用所有类(包括已编译的JSP),迟早会通过垃圾回收清除类和类加载器。但是webapp可能在DriverManager中注册了一个数据库驱动程序,或者使用了一些bean introspection(很可能通过一个流行的第三方库进行间接反应),这样可以保持bean元数据的缓存,从而使用webapp中的类在取消部署webapp之后,classloader仍然存在,仍然被webapp的类加载器未加载的其他对象强烈引用。

Tomcat有一个page describing a few of the possible leak scenarios以及它是如何运作的。

但是如果正确编写自定义类加载器不会导致泄漏。

答案 1 :(得分:2)

类加载器不存储在PermGen空间中。类数据存储在那里,它只与进行加载的类加载器间接相关:类加载器保存对它已加载的每个类的引用。

This answer提供了很好的信息,除了一件事:在PermGen空间中分配类加载器是错误的。类加载器只是普通的Java类,而PermGen只包含非常规对象数据的特殊材料。例如,它包含所有静态类变量和方法的可执行代码。

可以找到关于HotSpot内存布局和垃圾收集细节的重要资源here