【问题标题】:dead class loaders not garbage collected from permgen死类加载器不是从 permgen 收集的垃圾
【发布时间】:2015-05-01 13:48:14
【问题描述】:

我从“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 空间

我设置了以下 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 标志清理这些死类加载器?我该如何解决这个问题?

【问题讨论】:

    标签: java garbage-collection jvm xalan permgen


    【解决方案1】:

    你有一个类加载器泄漏。典型的模式是这样的。

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

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

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

    但是Class 有一个getClassloader 方法,所以类加载器对象也必须是可访问的。

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


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

    【讨论】:

    • 请注意,对 ClassB 的“引用”可能只是 ClassA 具有 ClassB 类型的空引用变量,或者包含具有 ClassB 参数的方法调用。甚至不需要 ClassA 的实例。这意味着您总是必须使用按名称查找方案来从其类加载器之外的东西引用 ClassB,并且必须始终使用接口或超类来引用其实例。
    • 什么会导致丢弃类加载器?
    • 类加载器只有在它变得不可访问时才能被垃圾回收。
    【解决方案2】:

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

    祝你好运!

    附:如果您调试它并发现 Xalan 内部存在泄漏,请告诉我,以便我更新the list of known offenders

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-10
      • 2014-03-20
      • 2018-12-30
      • 1970-01-01
      • 2011-02-18
      • 2023-04-03
      • 1970-01-01
      • 2016-02-29
      相关资源
      最近更新 更多