CMS回收器gclog分析

2016-10-16T15:42:04.951+0800: 229702.081: [GC [1 CMS-initial-mark: 1479564K(2097152K)] 1970155K(3984640K), 3.2226160 secs] [Times: user=3.23 sys=0.00, real=3.22 secs] 
##初始标记 stop-customer-thread{因此此阶段标记的对象只是从root集最直接可达的对象}
2016-10-16T15:42:08.174+0800: 229705.304: [CMS-concurrent-mark-start]
2016-10-16T15:42:10.193+0800: 229707.323: [CMS-concurrent-mark: 1.895/2.019 secs] [Times: user=11.04 sys=0.22, real=2.02 secs] 
##开始并发标记 no-stop-customer-thread{此阶段是和应用线程并发执行的,所谓并发收集器指的就是这个,主要作用是标记可达的对象}
2016-10-16T15:42:10.193+0800: 229707.323: [CMS-concurrent-preclean-start]
2016-10-16T15:42:10.203+0800: 229707.333: [CMS-concurrent-preclean: 0.009/0.010 secs] [Times: user=0.04 sys=0.00, real=0.01 secs]
##开始预清理preclean{并发}阶段 ---{此阶段主要是进行一些预清理,因为标记和应用线程是并发执行的,因此会有些对象的状态在标记后会改变,此阶段正是解决这个问题}
##---重点-start
2016-10-16T15:42:40.380+0800: 229737.510: [CMS-concurrent-abortable-preclean-start]
 CMS: abort preclean due to time 2016-10-16T15:42:45.454+0800: 229742.584: [CMS-concurrent-abortable-preclean: 1.510/5.073 secs] [Times: user=11.25 sys=0.32, real=5.07 secs]
##---重点-end
##终止preclean
2016-10-16T15:42:45.516+0800: 229742.646: [GC[YG occupancy: 660948 K (1887488 K)] ##yonggc情况
    2016-10-16T15:42:45.516+0800: 229742.646: [Rescan (parallel) , 2.6980830 secs] ##第二个stop-customer-thread阶段了,即Rescan阶段,此阶段暂停应用线程,对对象进行重新扫描并
     标记 花费了2.6秒
    2016-10-16T15:42:48.214+0800: 229745.344: [weak refs processing, 0.0000400 secs] ##若引用耗时
    2016-10-16T15:42:48.214+0800: 229745.344: [scrub string table, 0.0019500 secs]  ##类卸载耗时
                          [1 CMS-remark: 1479888K(2097152K)] 2140836K(3984640K), 2.7003330 secs] ##老年代-remark耗时
                          [Times: user=21.08 sys=0.03, real=2.70 secs] 
<>
    
##stop-customer-thread 阶段,从根及被其引用对象开始,重新扫描 CMS 堆中残留的更新过的对象。
2016-10-16T15:42:48.216+0800: 229745.346: [CMS-concurrent-sweep-start]
2016-10-16T15:42:49.057+0800: 229746.187: [CMS-concurrent-sweep: 0.774/0.840 secs] [Times: user=1.93 sys=0.06, real=0.84 secs]
##并发垃圾清理 no-stop-customer-thread
2016-10-16T15:42:49.057+0800: 229746.187: [CMS-concurrent-reset-start]
2016-10-16T15:42:49.064+0800: 229746.194: [CMS-concurrent-reset: 0.007/0.007 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
##最后。为下一次cms gc重置相关数据结构 no-stop-customer-thread
2016-10-16T15:42:49.641+0800: 229746.771: [GC [1 CMS-initial-mark: 1479877K(2097152K)] 2229843K(3984640K), 3.3950880 secs] [Times: user=3.40 sys=0.00, real=3.40 secs] 
## 下一次标记阶段 

综上所述:
    a.之前问题发生在配置-XX:CMSInitiatingOccupancyFraction=70,老年代被占用70%时,才进行cms-gc的intial-mark-preclean-rescan-sweep-reset。当时jvm总容量是4g,新生到2g,老年代2g,老年代的70%是1467mb,那么剩下的也就不到600m,此时问题有两个:1.如果此时有大对象通过空间担保机制直接从新生代逾越到老年代,此时系统可能直接宕机。2.1467mb的老年代容量不算小,虽然cms是concurrent进行标记-整理,但是过多的对象会导致上面log中的CMS-initial-mark、Rescan-remark 压力巨大,每次时间都达到了2~3秒,这种开销是要命的,这就是为什么系统半死不活的状态,对外服务tp拉高。
    b.从日志中分析得出: CMS: abort preclean due to time。这句话翻译过来是说:cms 终止了preclean操作花费时间是5.073s 这是一个浪费的开销,预清理操作明细是一个优化清理的动作,结果成为负担了。这里也是我们着重优化的点:-XX:CMSMaxAbortablePrecleanTime=500(单位是毫秒) 来约束preclean动作,还可以用其他参数进行约束preclean如:-XX:CMSScheduleRemarkEdenPenetration、-XX:CMSScheduleRemarkEdenPenetration

    c.年轻代的优化也是这次的重点:年轻代设置过大会这样?


有2种情况会触发full gc,在full gc时,整个应用会暂停
a)concurrent-mode-failure:当cms gc正进行时,此时有新的对象要进行old代,但是old代空间不足造成的
b)promotion-failed:当进行young gc时,有部分young代对象仍然可用,但是S1或S2放不下,
    因此需要放到old代,但此时old代空间无法容纳此

你可能感兴趣的:(CMS回收器gclog分析)