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 failure
是CMS
特有的错误,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区过小,导致晋升速率过快
- 存在大对象