CMS收集器中两个致命的问题

CMS是一个很好的并发垃圾收集器,可是使用过程当中会产生两个重要的问题。

  • promotion failed 晋升失败
  • concurrent mode failure 收集器没法处理浮动垃圾

promotion failed 晋升失败缘由

该问题发生在 Minor GC过程当中, Survivor Space放不下转移的对象,老年代也放不下(promotion failed发生的时候老年代CMS尚未机会进行回收,又放不下转移到老年代的对象,下一步就会产生 concurrent mode fialure,发生STW降级为Serial Old)

下面是一条promotion failed失败的日志并发

106.641: [GC 106.641: [ParNew (promotion failed): 14784K->14784K(14784K), 0.0370328 secs]106.678: [CMS106.715: [CMS-concurrent-mark: 0.065/0.103 secs] [Times: user=0.17 sys=0.00, real=0.11 secs]
(concurrent mode failure): 41568K->27787K(49152K), 0.2128504 secs] 52402K->27787K(63936K), [CMS Perm : 2086K->2086K(12288K)], 0.2499776 secs] [Times: user=0.28 sys=0.00, real=0.25 secs]

concurrent mode failure产生的缘由

concurrent mode failureCMS特有的错误, CMS的垃圾清理线程和用户线程是并行进行的. 老年代正在清理,从年轻代晋升了新对象,或者分配的大对象在新生代放不下,直接在老年代分配内存,这时老年代也放不下,则会抛出 concurrent mode failure

concurrent mode failure的影响

老年代的垃圾收集器从 CMS退化成 Serial Old,全部用户线程被暂停,停顿时间变长。

解决方案

CMS触发太晚

-XX:CMSInitiatingOccupancyFraction=N 是指设定CMS在对内存占用率达到N%的时候开始GC(由于CMS会有浮动垃圾,因此通常都较早启动GC);
  • 将:-XX:CMSInitiatingOccupancyFraction=N调小

空间碎片太多

开启空间碎片整理,并将空间碎片整理周期设置在合理范围,- XX:CMSFullGCsBeforeCompaction做用:设置在执行多少次Full GC后对内存空间进行压缩整理。
  • -XX:+UseCMSCompactAtFullCollection (空间碎片整理)
  • -XX:CMSFullGCsBeforeCompaction=n

垃圾产生太快

  • 晋升阈值过小
  • Survivor空间太小
  • Eden区太小,致使晋升速率过快
  • 存在大对象

相关文章
相关标签/搜索