java – 死类加载器不是从permgen收集的垃圾

我在“jmap -permstat”中看到以下内容:

0x000000077736cce0      12      173472  0x00000007723425d0      dead    com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl$TransletClassLoader@0x00000007c83bea70
0x0000000777168a20      12      172264  0x00000007723425d0      dead    com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl$TransletClassLoader@0x00000007c83bea70
0x0000000780b3c810      12      172264  0x00000007723425d0      dead    com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl$TransletClassLoader@0x00000007c83bea70
0x0000000776ca6170      12      172264  0x00000007723425d0      dead    com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl$TransletClassLoader@0x00000007c83bea70
0x00000007772b28a8      12      172264  0x00000007723425d0      dead    com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl$TransletClassLoader@0x00000007c83bea70
....

permGen中有超过6000个这些死的TransletClassLoader类加载器,并且数字一直在增长,直到我收到此错误:

java.lang.OutOfMemoryError: PermGen space

我设置了以下JVM标志:

-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled

java version "1.6.0_33"
Java(TM) SE Runtime Environment (build 1.6.0_33-b04)
Java HotSpot(TM) 64-Bit Server VM (build 20.8-b03, mixed mode)

为什么这些死类加载器没有被CMSClassUnloadingEnabled标志清除?我该如何解决这个问题?

最佳答案
你有一个classloader泄漏.典型的模式是这样的.

>您创建新的类加载器
>您在新的类加载器中加载类
>您可以从其中一个类创建实例.
>您将实例放入数据结构(例如),使其永久可访问.
>您放弃对类加载器的引用.

问题是只要您创建的实例是可访问的,我们需要1)实例的类方法的代码2)Class对象(或创建它的infor)以防有人在实例上调用getClass().

这意味着(实际上)该类必须是可访问的.

但是Class有一个getClassloader方法,因此classloader对象也必须是可访问的.

典型的类加载器对象具有对其加载的所有类的内部引用,因此它们也必须都可以访问.

简而言之,请确保您没有保留对使用死类加载器加载的类实例的引用.它们将阻止类加载器被垃圾收集.

转载注明原文:java – 死类加载器不是从permgen收集的垃圾 - 代码日志