CMS日志分析

CMS日志及对应阶段

CMS 收集器是老年代经常使用的收集器,它采用的是标记-清楚算法,应用程序在发生一次 Full GC 时,典型的 GC 日志信息如下:

// 阶段1:Initial Mark
[GC (CMS Initial Mark) [1 CMS-initial-mark: 0K(2097152K)] 620856K(3040896K), 0.1337462 secs] [Times: user=0.36 sys=0.00, real=0.13 secs] 

// 阶段2:并发标记
2019-06-24T14:26:28.421+0800: 4.344: [CMS-concurrent-mark-start]
2019-06-24T14:26:28.448+0800: 4.370: [CMS-concurrent-mark: 0.026/0.026 secs] [Times: user=0.08 sys=0.01, real=0.03 secs] 

// 阶段3:Concurrent Preclean
2019-06-24T14:26:28.448+0800: 4.370: [CMS-concurrent-preclean-start]
2019-06-24T14:26:28.452+0800: 4.375: [CMS-concurrent-preclean: 0.004/0.004 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 

// 阶段4:Concurrent Abortable Preclean
2019-06-24T14:26:28.452+0800: 4.375: [CMS-concurrent-abortable-preclean-start]
2019-06-24T14:26:28.892+0800: 4.815: [GC (Allocation Failure) 2019-06-24T14:26:28.892+0800: 4.815: [ParNew2019-06-24T14:26:28.946+0800: 4.868: [CMS-concurrent-abortable-preclean: 0.066/0.493 secs] [Times: user=1.79 sys=0.09, real=0.49 secs] 
: 838912K->92239K(943744K), 0.1086553 secs] 838912K->92239K(3040896K), 0.1088052 secs] [Times: user=0.31 sys=0.05, real=0.11 secs] 

// 阶段5:Final Remark
2019-06-24T14:26:29.001+0800: 4.924: [GC (CMS Final Remark) [YG occupancy: 113547 K (943744 K)]2019-06-24T14:26:29.001+0800: 4.924: [Rescan (parallel) , 0.0273029 secs]2019-06-24T14:26:29.029+0800: 4.951: [weak refs processing, 0.0000370 secs]2019-06-24T14:26:29.029+0800: 4.951: [class unloading, 0.0057905 secs]2019-06-24T14:26:29.035+0800: 4.957: [scrub symbol table, 0.0038963 secs]2019-06-24T14:26:29.038+0800: 4.961: [scrub string table, 0.0006268 secs][1 CMS-remark: 0K(2097152K)] 113547K(3040896K), 0.0391238 secs] [Times: user=0.13 sys=0.00, real=0.04 secs] 

// 阶段6:Concurrent Sweep
2019-06-24T14:26:29.041+0800: 4.963: [CMS-concurrent-sweep-start]
2019-06-24T14:26:29.041+0800: 4.963: [CMS-concurrent-sweep: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

// 阶段7:Concurrent Reset.
2019-06-24T14:26:29.041+0800: 4.963: [CMS-concurrent-reset-start]
2019-06-24T14:26:29.049+0800: 4.971: [CMS-concurrent-reset: 0.008/0.008 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 


阶段1:Initial Mark

这个是 CMS 两次 stop-the-wolrd 事件的其中一次,这个阶段的目标是:标记那些直接被 GC root 引用或者被年轻代存活对象所引用的所有对象,标记后示例如下所示(插图来自:GC Algorithms:Implementations —— Concurrent Mark and Sweep —— Full GC):

CMS 初始标记阶段

上述例子对应的日志信息为:

[GC (CMS Initial Mark) [1 CMS-initial-mark: 0K(2097152K)] 620856K(3040896K), 0.1337462 secs] [Times: user=0.36 sys=0.00, real=0.13 secs] 

CMS-initial-mark:初始标记阶段,它会收集所有 GC Roots 以及其直接引用的对象;
0K:当前老年代使用的容量,这里是 0G;
(2097152K):老年代可用的最大容量,这里是 2G;
620856K:整个堆目前使用的容量,这里是 600M;
(3040896K):堆可用的容量,这里是 3G;
0.1337462 secs:这个阶段的持续时间;
[Times: user=0.04 sys=0.00, real=0.04 secs]:相应 user、system and real 的时间统计。


阶段2:并发标记

在这个阶段 Garbage Collector 会遍历老年代,然后标记所有存活的对象,它会根据上个阶段找到的 GC Roots 遍历查找。并发标记阶段,它会与用户的应用程序并发运行。并不是老年代所有的存活对象都会被标记,因为在标记期间用户的程序可能会改变一些引用,如下图所示(插图来自:GC Algorithms:Implementations —— Concurrent Mark and Sweep —— Full GC):

CMS 并发标记阶段

在上面的图中,与阶段1的图进行对比,就会发现有一个对象的引用已经发生了变化,这个阶段相应的日志信息如下:

2019-06-24T14:26:28.421+0800: 4.344: [CMS-concurrent-mark-start]
2019-06-24T14:26:28.448+0800: 4.370: [CMS-concurrent-mark: 0.026/0.026 secs] [Times: user=0.08 sys=0.01, real=0.03 secs] 

这里详细对上面的日志解释,如下所示:

CMS-concurrent-mark:并发收集阶段,这个阶段会遍历老年代,并标记所有存活的对象;
0.138/0.138 secs:这个阶段的持续时间与时钟时间;
[Times: user=1.01 sys=0.21, real=0.14 secs]:如前面所示,但是这部的时间,其实意义不大,因为它是从并发标记的开始时间开始计算,这期间因为是并发进行,不仅仅包含 GC 线程的工作。


阶段3:Concurrent Preclean

Concurrent Preclean:这也是一个并发阶段,与应用的线程并发运行,并不会 stop 应用的线程。在并发运行的过程中,一些对象的引用可能会发生变化,但是这种情况发生时,JVM 会将包含这个对象的区域(Card)标记为 Dirty,这也就是 Card Marking。如下图所示(插图来自:GC Algorithms:Implementations —— Concurrent Mark and Sweep —— Full GC

Concurrent Preclean 1

在pre-clean阶段,那些能够从 Dirty 对象到达的对象也会被标记,这个标记做完之后,dirty card 标记就会被清除了,如下(插图来自:GC Algorithms:Implementations —— Concurrent Mark and Sweep —— Full GC

Concurrent Preclean 2

这个阶段相应的日志信息如下:

2019-06-24T14:26:28.448+0800: 4.370: [CMS-concurrent-preclean-start]
2019-06-24T14:26:28.452+0800: 4.375: [CMS-concurrent-preclean: 0.004/0.004 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 

其含义为:
CMS-concurrent-preclean:Concurrent Preclean 阶段,对在前面并发标记阶段中引用发生变化的对象进行标记;
0.056/0.057 secs:这个阶段的持续时间与时钟时间;
[Times: user=0.20 sys=0.12, real=0.06 secs]:同并发标记阶段中的含义。


阶段4:Concurrent Abortable Preclean

这也是一个并发阶段,但是同样不会影响影响用户的应用线程,这个阶段是为了尽量承担 STW(stop-the-world)中最终标记阶段的工作。这个阶段持续时间依赖于很多的因素,由于这个阶段是在重复做很多相同的工作,直接满足一些条件(比如:重复迭代的次数、完成的工作量或者时钟时间等)。这个阶段的日志信息如下:

2019-06-24T14:26:28.452+0800: 4.375: [CMS-concurrent-abortable-preclean-start]
2019-06-24T14:26:28.946+0800: 4.868: [CMS-concurrent-abortable-preclean: 0.066/0.493 secs] [Times: user=1.79 sys=0.09, real=0.49 secs] 


阶段5:Final Remark

这是第二个 STW 阶段,也是 CMS 中的最后一个,这个阶段的目标是标记所有老年代所有的存活对象,由于之前的阶段是并发执行的,gc 线程可能跟不上应用程序的变化,为了完成标记老年代所有存活对象的目标,STW 就非常有必要了。

通常 CMS 的 Final Remark 阶段会在年轻代尽可能干净的时候运行,目的是为了减少连续 STW 发生的可能性(年轻代存活对象过多的话,也会导致老年代涉及的存活对象会很多)。这个阶段会比前面的几个阶段更复杂一些,相关日志如下:

2019-06-24T14:26:29.001+0800: 4.924: [GC (CMS Final Remark) [YG occupancy: 113547 K (943744 K)]2019-06-24T14:26:29.001+0800: 4.924: [Rescan (parallel) , 0.0273029 secs]2019-06-24T14:26:29.029+0800: 4.951: [weak refs processing, 0.0000370 secs]2019-06-24T14:26:29.029+0800: 4.951: [class unloading, 0.0057905 secs]2019-06-24T14:26:29.035+0800: 4.957: [scrub symbol table, 0.0038963 secs]2019-06-24T14:26:29.038+0800: 4.961: [scrub string table, 0.0006268 secs][1 CMS-remark: 0K(2097152K)] 113547K(3040896K), 0.0391238 secs] [Times: user=0.13 sys=0.00, real=0.04 secs] 

对上面的日志进行分析:

YG occupancy: 1805641 K (3774912 K):年轻代当前占用量及容量,这里分别是 1.71G 和 3.6G;
[Rescan (parallel) , 0.0429390 secs]:这个 Rescan 是当应用暂停的情况下完成对所有存活对象的标记,这个阶段是并行处理的,这里花费了 0.0429390s;
[weak refs processing, 0.0027800 secs]:第一个子阶段,它的工作是处理弱引用;
[class unloading, 0.0033120 secs]:第二个子阶段,它的工作是:unloading the unused classes;
[scrub symbol table, 0.0016780 secs] ... [scrub string table, 0.0004780 secs]:最后一个子阶段,它的目的是:cleaning up symbol and string tables which hold class-level metadata and internalized string respectively,时钟的暂停也包含在这里;
0K(2097152K):这个阶段之后,老年代的使用量与总量,这里分别是 0G 和 2G;
113547K(3040896K):这个阶段之后,堆的使用量与总量(包括年轻代,年轻代在前面发生过 GC),这里分别是 100M 和 3G;
0391238 secs:这个阶段的持续时间;
[Times: user=0.13 sys=0.00, real=0.04 secs]:对应的时间信息。
经历过这五个阶段之后,老年代所有存活的对象都被标记过了,现在可以通过清除算法去清理那些老年代不再使用的对象。


阶段6:Concurrent Sweep

这里不需要 STW,它是与用户的应用程序并发运行,这个阶段是:清除那些不再使用的对象,回收它们的占用空间为将来使用。如下图所示(插图来自:GC Algorithms:Implementations —— Concurrent Mark and Sweep —— Full GC
):

CMS Concurrent Sweep 阶段

这个阶段对应的日志信息如下(这中间又发生了一次 Young GC):

2019-06-24T14:26:29.041+0800: 4.963: [CMS-concurrent-sweep-start]
2019-06-24T14:26:29.041+0800: 4.963: [CMS-concurrent-sweep: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 


阶段7:Concurrent Reset.

这个阶段也是并发执行的,它会重设 CMS 内部的数据结构,为下次的 GC 做准备,对应的日志信息如下:

2019-06-24T14:26:29.041+0800: 4.963: [CMS-concurrent-reset-start]
2019-06-24T14:26:29.049+0800: 4.971: [CMS-concurrent-reset: 0.008/0.008 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] 


参考文章

GC Algorithms: Implementations

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352