死亡的装载机不是从permgen收集的垃圾

时间:2015-03-01 01:11:05

标签: java garbage-collection jvm xalan 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标志清除?我该如何解决这个问题?

2 个答案:

答案 0 :(得分:4)

你有一个classloader泄漏。典型的模式是这样的。

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

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

这意味着(实际上)必须可以访问该类。

ClassgetClassloader方法,因此类加载器对象也必须可以访问。

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


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

答案 1 :(得分:1)

作为Stephens anser的后续内容,您可能需要查看this blog series of mine以了解如何跟踪类加载器泄漏。 或者您可能只想跳过并向您的应用程序添加my Classloader Leak Prevention library

祝你好运!

P.S。如果您进行调试并发现Xalan内部存在泄漏,请告知我们,以便我可以更新the list of known offenders