【问题标题】:permgen garbage collection takes multiple Full GCpermgen 垃圾回收需要多次 Full GC
【发布时间】:2013-06-02 22:19:06
【问题描述】:

我们正在运行 grails,我们注意到需要多次完整的垃圾回收来清除 permgen 空间。

2013-06-06T16:11:27.016+0000: 32582.145: [Full GC 32582.145: [CMS2013-06-06T16:11:45.404+0000:     32600.532: [CMS-concurrent-mark: 21.403/86.063 secs] [Times: user=48.44 sys=0.63, real=86.07 secs]
(concurrent mode failure): 7585874K->7290466K(10145024K), 57.9230770 secs] 7866094K->7290466K(10451712K), [CMS Perm : 261766K->261702K(262144K)] icms_dc=30 , 57.9232150 secs] [Times: user=57.97 sys=0.00, real=57.93 secs]
2013-06-06T16:12:25.183+0000: 32640.311: [GC [1 CMS-initial-mark: 7290466K(10145024K)] 7385976K(10451712K), 0.0880890 secs] [Times: user=0.09 sys=0.00, real=0.08 secs]
2013-06-06T16:12:25.271+0000: 32640.400: [CMS-concurrent-mark-start]
2013-06-06T16:12:25.427+0000: 32640.555: [GC 32640.556: [ParNew: 272640K->10006K(306688K), 0.0622620 secs] 7563106K->7300472K(10451712K) icms_dc=30 , 0.0624140 secs] [Times: user=0.24 sys=0.00, real=0.06 secs]
2013-06-06T16:12:25.734+0000: 32640.863: [GC 32640.863: [ParNew: 282646K->13476K(306688K), 0.0648770 secs] 7573112K->7303942K(10451712K) icms_dc=30 , 0.0650170 secs] [Times: user=0.26 sys=0.00, real=0.07 secs]
2013-06-06T16:12:26.013+0000: 32641.142: [GC 32641.142: [ParNew: 286116K->11277K(306688K), 0.0607460 secs] 7576582K->7301743K(10451712K) icms_dc=30 , 0.0608870 secs] [Times: user=0.25 sys=0.00, real=0.06 secs]
2013-06-06T16:12:32.449+0000: 32647.577: [GC 32647.577: [ParNew: 283917K->17560K(306688K), 0.0672260 secs] 7574383K->7308026K(10451712K) icms_dc=30 , 0.0673710 secs] [Times: user=0.27 sys=0.00, real=0.07 secs]
2013-06-06T16:12:33.107+0000: 32648.236: [GC 32648.236: [ParNew: 290200K->22523K(306688K), 0.0686820 secs] 7580666K->7312989K(10451712K) icms_dc=30 , 0.0688200 secs] [Times: user=0.28 sys=0.00, real=0.07 secs]
2013-06-06T16:12:33.845+0000: 32648.974: [Full GC 32648.974: [CMS2013-06-06T16:12:52.516+0000: 32667.645: [CMS-concurrent-mark: 21.346/27.245 secs] [Times: user=27.55 sys=0.14, real=27.25 secs]
(concurrent mode failure): 7290466K->7293289K(10145024K), 57.7092090 secs] 7523492K->7293289K(10451712K), [CMS Perm : 262143K->262143K(262144K)] icms_dc=30 , 57.7093560 secs] [Times: user=57.76 sys=0.00, real=57.71 secs]
2013-06-06T16:13:31.557+0000: 32706.686: [Full GC 32706.686: [CMS: 7293289K->6960613K(10145024K), 37.1325250 secs] 7293289K->6960613K(10451712K), [CMS Perm : 262143K->91949K(262144K)] icms_dc=30 , 37.1326670 secs] [Times: user=37.19 sys=0.00, real=37.14 secs]

第一个只收集 64K,第二个什么都不收集,最后第三个可以收集 170194K

JAVA_OPTIONS:
-XX:+CMSClassUnloadingEnabled 
-XX:+CMSPermGenSweepingEnabled 
-XX:+UseConcMarkSweepGC
-XX:MaxPermSize=256m 
-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-XX:+PrintGCDateStamps 
-verbose:gc,sizes 
-XX:+UseConcMarkSweepGC 
-XX:CMSInitiatingOccupancyFraction=80 
-XX:+DisableExplicitGC 
-XX:+CMSIncrementalMode 
-XX:+UseParNewGC  
-Xms10g -Xmx10g

另外,有没有办法告诉垃圾收集器对 permgen 空间进行增量扫描?我们只看到在完全收集期间 permgen 会减少。

【问题讨论】:

  • 你运行的是什么 Hotspot 版本?
  • 我们使用 grails 中的一个特性对一个表达式执行 Eval.me(),该表达式编译了一个类并杀死了我们的 permgen 空间。我们通过创建闭包并重用它们而不是每次都执行 Eval 来修复它。

标签: java grails garbage-collection permgen


【解决方案1】:

让我澄清一下并发标记扫描及其增量模式算法。引入了 CMS 增量模式,以避免在后台 GC 运行时单核服务器上的 CPU 不足。 不鼓励使用增量 CMS。

增量模式不会增量释放内存,它只是在标记扫描算法的标记阶段进行长时间睡眠。

-XX:+CMSPermGenSweepingEnabled 已弃用,与 -XX:+CMSClassUnloadingEnabled 同义

增量模式在某种程度上隐藏了死物检测,我是个问题。

此外,如果任何类(要卸载)具有 finilazer,这也可以解释 2 个集合(JVM 无法卸载单个类,整个类加载器被卸载,因此它的任何类都可以阻止收集)。

我建议您适当调整堆大小和 perm gen,如果您想保持该级别的堆利用率,请将 CMS 配置为更具侵略性。在my blog 你可以找到一些关于调整 CMS 的建议。

但是,如果您的运行时正在积极生产并放弃调整 GC 的类加载器可能还不够。

我在自动化测试中遇到了类似的问题(为了隔离,每个测试都在专用的类加载器中加载相同的类)。测试通常不稳定,在 perm gen 中抛出 OOME。解决方案是通过使用垃圾数据(here is snippet of code)来强制 JVM 清理 perm gen。但它导致了 Full GC - 可能不是您希望看到的。

顺便说一句 还有-XX:CMSClassUnloadingMaxInterval=N 标志,它让JVM 只在每第N 个收集时收集Perm gen。但这不是你的情况,因为 perm gen 已满。

【讨论】:

    【解决方案2】:

    识别上次 FullGC 收集中收集的内容的一种方法是在 Full GC 之前/之后打印类直方图-XX:+PrintClassHistogramBeforeFullGC -XX:+PrintClassHistogramAfterFullGC

    通过这种方式,您可以比较所有集合的直方图,并确定在最后一个集合中收集了哪些类。

    对于考虑 PermGen 的第二个问题,通常的建议是确定 PermGen 的大小足以满足您的应用程序/工作负载并坚持下去。您需要调查为什么有这么多的对象被放置到 PermGen 中。

    【讨论】:

      猜你喜欢
      • 2012-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-20
      • 1970-01-01
      相关资源
      最近更新 更多