java9系列(九)Make G1 the Default Garbage Collector

本文主要研究下JEP 248: Make G1 the Default Garbage Collector

默认垃圾收集器

java9废弃了CMS垃圾收集器,并把G1提升为默认垃圾收集器,替代了原来的吞吐优先的ParallelOldGC

Region

G1相对于之前的垃圾收集器最大的不同是引入了Region。G1虽然也是基于分代机制,但是各个generation的空间不再连续,如下图:


image

可以用-XX:G1HeapRegionSize=16m来指定Region Size,注意它必须是2的乘方,范围在1MB到32MB之间。目标是根据最小的Java堆大小划分出约2048 个区域.

Min Heap Size Region Size
heap < 4GB 1MB
4GB <= heap < 8GB 2MB
8GB <= heap < 16GB 4MB
16GB <= heap < 32GB 8MB
32GB <= heap < 64GB 16MB
64GB <= heap 32MB

如果没有明确指定,则自动根据Heap Size来指定,其对应关系如下:

Min Heap Size Region Size
heap < 4GB 1MB
4GB <= heap < 8GB 2MB
8GB <= heap < 16GB 4MB
16GB <= heap < 32GB 8MB
32GB <= heap < 64GB 16MB
64GB <= heap 32MB

Humongous Object/ Humongous区域

  • 对于G1 GC,任何超过区域一半大小的对象都被视为“巨型对象”。
  • 此类对象直接被分配到老年代中的“巨型区域”。
  • 这些巨型区域是一个连续的区域集。StartsHumongous 标记该连续集的开始,ContinuesHumongous 标记它的延续。

巨型对象默认直接会被分配在年老代,但是如果它是一个短期存在的巨型对象,就会对垃圾收集器造成负面影响。为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象。如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC。

GC事件及触发

GC event

  • Minor GC event

正常的young gc

  • Mixed GC event

Minor GC + (# reclaimable Tenured regions / -XX:G1MixedGCCountTarget) regions of Tenured

  • Full GC event

All regions evacuated,通常Humongous object太多会耗尽空间,导致Full GC

  • Minor/Mixed + To-space exhaustion

Minor/Mixed + rollback + Full GC

触发时机

  • Eden满/空间不够
  • 剩余空间不够容纳一个Humongous object
  • Humongous object分配成功,同时符合一些GC条件
  • 外部命令触发(jcmd, jmap, Runtime.gc())

G1 GC分类

主要分为:Minor GC,Mixed/Old GC

Minor GC/Young GC(STW)

Young GC主要是对Eden区进行GC,它在Eden空间不够时会被触发。Eden空间的数据移动到Survivor空间中,如果Survivor空间不够,Eden空间的部分数据会直接晋升到年老代空间。From Survivor区的数据移动到To Survivor区中,也有部分数据晋升到老年代空间中。

阶段 执行动作
阶段1 根扫描 静态和本地对象被扫描
阶段2 更新RS 处理dirty card队列更新RS
阶段3 处理RS 检测从年轻代指向年老代的对象
阶段4 对象拷贝 拷贝存活的对象到survivor/old区域
阶段5 处理引用队列 软引用,弱引用,虚引用处理

其阶段主要如下:

阶段 执行动作
阶段1 根扫描 静态和本地对象被扫描
阶段2 更新RS 处理dirty card队列更新RS
阶段3 处理RS 检测从年轻代指向年老代的对象
阶段4 对象拷贝 拷贝存活的对象到survivor/old区域
阶段5 处理引用队列 软引用,弱引用,虚引用处理

Mixed/Old GC(STW)

主要是对年老代进行并发标记然后进行GC,其中部分阶段涉及到ygc,同时既有ygc及old gc的部分称为mixed gc。

阶段 执行动作
(1) Initial Mark(Stop the World Event) 初始标记阶段 在此阶段G1 GC对根进行标记。该阶段与常规的 (STW) 年轻代垃圾回收密切相关。日志标记为Pause Initial Mark (G1 Evacuation Pause).
(2) Root Region Scanning 根区域扫描阶段 G1 GC在初始标记的存活区扫描对老年代的引用,并标记被引用的对象。该阶段与应用程序(非 STW)同时运行,并且只有完成该阶段后,才能开始下一次STW年轻代垃圾回收。
(3) Concurrent Marking 并发标记阶段 G1 GC在整个堆中查找可访问的(存活的)对象。该阶段与应用程序同时运行,可以被 STW 年轻代垃圾回收中断。
(4) Remark(Stop the World Event) 重新标记阶段 该阶段是STW回收,帮助完成标记周期。G1 GC清空SATB缓冲区,跟踪未被访问的存活对象,并执行引用处理。
(5) Copying(Stop the World Event) / Cleanup(Stop the World Event and Concurrent) 拷贝/清理阶段 在这个最后阶段,G1 GC为了更快进行垃圾回收,会选择那些存活率低的region进行拷贝,即evacuate或者拷贝存活对象到新的空闲的regions,然后清理回收该region,此时会STW,如果是在年轻代产生的,则日志标记为Pause Young (G1 Evacuation Pause),如果年轻代和年老代都进行这个动作,则日志标记为Pause Mixed (G1 Evacuation Pause).

并发标记周期(Concurrent Marking Cycle Phases)阶段如下:

阶段 执行动作
(1) Initial Mark(Stop the World Event) 初始标记阶段 在此阶段G1 GC对根进行标记。该阶段与常规的 (STW) 年轻代垃圾回收密切相关。日志标记为Pause Initial Mark (G1 Evacuation Pause).
(2) Root Region Scanning 根区域扫描阶段 G1 GC在初始标记的存活区扫描对老年代的引用,并标记被引用的对象。该阶段与应用程序(非 STW)同时运行,并且只有完成该阶段后,才能开始下一次STW年轻代垃圾回收。
(3) Concurrent Marking 并发标记阶段 G1 GC在整个堆中查找可访问的(存活的)对象。该阶段与应用程序同时运行,可以被 STW 年轻代垃圾回收中断。
(4) Remark(Stop the World Event) 重新标记阶段 该阶段是STW回收,帮助完成标记周期。G1 GC清空SATB缓冲区,跟踪未被访问的存活对象,并执行引用处理。
(5) Copying(Stop the World Event) / Cleanup(Stop the World Event and Concurrent) 拷贝/清理阶段 在这个最后阶段,G1 GC为了更快进行垃圾回收,会选择那些存活率低的region进行拷贝,即evacuate或者拷贝存活对象到新的空闲的regions,然后清理回收该region,此时会STW,如果是在年轻代产生的,则日志标记为Pause Young (G1 Evacuation Pause),如果年轻代和年老代都进行这个动作,则日志标记为Pause Mixed (G1 Evacuation Pause).

核心的阶段主要是Concurrent Marking Phase、Remark Phase、Copying/Cleanup Phase

相关参数

参数 含义
-XX:G1HeapRegionSize=n 设置Region大小,并非最终值
-XX:MaxGCPauseMillis=200 设置G1收集过程目标时间,默认值200ms,不是硬性条件
-XX:G1NewSizePercent=5 新生代最小值,默认值5%
-XX:G1MaxNewSizePercent=60 新生代最大值,默认值60%
-XX:ParallelGCThreads=n STW期间,并行GC线程数,其值与逻辑处理器的数量相同,最多为8。如果逻辑处理器不止八个,则将n为逻辑处理器数的5/8
-XX:ConcGCThreads=n 并发标记阶段的并行标记线程数,ParallelGCThreads的 1/4 左右
-XX:InitiatingHeapOccupancyPercent=45 设置触发标记周期的Java堆占用率阈值。默认值是45%。这里的java堆占比指的是non_young_capacity_bytes,包括old+humongous
-XX:G1MixedGCLiveThresholdPercent=65 为混合垃圾回收周期中要包括的旧区域设置占用率阈值。默认占用率为 65%
-XX:G1HeapWastePercent=10 如果可回收百分比小于此值,JVM不会启动混合垃圾回收周期。默认值是10%
-XX:G1OldCSetRegionThresholdPercent=10 设置混合垃圾回收期间要回收的最大旧区域数。默认值是Java堆的10%
-XX:G1MixedGCCountTarget=8 设置标记周期完成后,对存活数据上限为 G1MixedGCLIveThresholdPercent 的旧区域执行混合垃圾回收的目标次数。默认8次混合垃圾回收,混合回收的目标是要控制在此目标次数以内
-XX:G1ReservePercent=10 设置作为空闲空间的预留内存百分比,以降低目标空间溢出的风险。默认值是10%。增加或减少百分比时,请确保对总的Java 堆调整相同的量

避免使用-Xmn选项或-XX:NewRatio等其他相关选项显式设置年轻代大小,固定年轻代的大小会禁用掉暂停时间(MaxGCPauseMillis)目标。

GC日志实例

简版使用-Xlog:gc=info,详细版使用-Xlog:gc*=info

ygc

  • 简版
[0.317s][info][gc] GC(37) Pause Young (G1 Evacuation Pause) 7M->6M(10M) 0.511ms
[0.324s][info][gc] GC(40) Pause Young (G1 Evacuation Pause) 7M->6M(10M) 0.709ms
  • 详细版
[0.011s][info][gc,heap] Heap region size: 1M
[0.012s][info][gc     ] Using G1
[0.012s][info][gc,heap,coops] Heap address: 0x00000007bf600000, size: 10 MB, Compressed Oops mode: Zero based, Oop shift amount: 3
[0.170s][info][gc,start     ] GC(0) Pause Young (G1 Evacuation Pause)
[0.170s][info][gc,task      ] GC(0) Using 8 workers of 8 for evacuation
[0.172s][info][gc,phases    ] GC(0)   Pre Evacuate Collection Set: 0.0ms
[0.172s][info][gc,phases    ] GC(0)   Evacuate Collection Set: 1.5ms
[0.172s][info][gc,phases    ] GC(0)   Post Evacuate Collection Set: 0.1ms
[0.172s][info][gc,phases    ] GC(0)   Other: 0.1ms
[0.172s][info][gc,heap      ] GC(0) Eden regions: 4->0(2)
[0.172s][info][gc,heap      ] GC(0) Survivor regions: 0->1(1)
[0.172s][info][gc,heap      ] GC(0) Old regions: 0->1
[0.172s][info][gc,heap      ] GC(0) Humongous regions: 0->0
[0.172s][info][gc,metaspace ] GC(0) Metaspace: 5982K->5982K(1056768K)
[0.172s][info][gc           ] GC(0) Pause Young (G1 Evacuation Pause) 4M->1M(10M) 1.718ms
[0.172s][info][gc,cpu       ] GC(0) User=0.01s Sys=0.00s Real=0.00s

old gc

  • 简版
[0.321s][info][gc] GC(38) Pause Initial Mark (G1 Evacuation Pause) 7M->6M(10M) 0.601ms
[0.321s][info][gc] GC(39) Concurrent Cycle
[0.324s][info][gc] GC(40) Pause Young (G1 Evacuation Pause) 7M->6M(10M) 0.709ms
[0.326s][info][gc] GC(39) Pause Remark 7M->7M(10M) 0.623ms
[0.326s][info][gc] GC(39) Pause Cleanup 7M->7M(10M) 0.104ms
[0.326s][info][gc] GC(39) Concurrent Cycle 5.398ms
[0.327s][info][gc] GC(41) Pause Young (G1 Evacuation Pause) 7M->6M(10M) 0.512ms
[0.331s][info][gc] GC(42) To-space exhausted
[0.331s][info][gc] GC(42) Pause Mixed (G1 Evacuation Pause) 7M->7M(10M) 1.190ms
[0.334s][info][gc] GC(43) Pause Initial Mark (G1 Evacuation Pause) 8M->7M(10M) 0.637ms
[0.334s][info][gc] GC(44) Concurrent Cycle
[0.338s][info][gc] GC(45) Pause Young (G1 Evacuation Pause) 8M->7M(10M) 0.553ms
[0.340s][info][gc] GC(44) Pause Remark 8M->8M(10M) 0.582ms
[0.341s][info][gc] GC(44) Pause Cleanup 8M->8M(10M) 0.100ms
[0.341s][info][gc] GC(44) Concurrent Cycle 6.195ms
  • 详细版
[0.942s][info][gc,start       ] GC(192) Pause Initial Mark (G1 Evacuation Pause)
[0.942s][info][gc,task        ] GC(192) Using 8 workers of 8 for evacuation
[0.942s][info][gc,phases      ] GC(192)   Pre Evacuate Collection Set: 0.0ms
[0.942s][info][gc,phases      ] GC(192)   Evacuate Collection Set: 0.4ms
[0.942s][info][gc,phases      ] GC(192)   Post Evacuate Collection Set: 0.0ms
[0.942s][info][gc,phases      ] GC(192)   Other: 0.0ms
[0.942s][info][gc,heap        ] GC(192) Eden regions: 0->0(1)
[0.942s][info][gc,heap        ] GC(192) Survivor regions: 0->0(1)
[0.942s][info][gc,heap        ] GC(192) Old regions: 10->10
[0.942s][info][gc,heap        ] GC(192) Humongous regions: 0->0
[0.942s][info][gc,metaspace   ] GC(192) Metaspace: 5993K->5993K(1056768K)
[0.942s][info][gc             ] GC(192) Pause Initial Mark (G1 Evacuation Pause) 9M->9M(10M) 0.530ms
[0.942s][info][gc,cpu         ] GC(192) User=0.00s Sys=0.00s Real=0.00s
[0.942s][info][gc             ] GC(193) Concurrent Cycle
[0.942s][info][gc,marking     ] GC(193) Concurrent Clear Claimed Marks
[0.942s][info][gc,marking     ] GC(193) Concurrent Clear Claimed Marks 0.004ms
[0.942s][info][gc,marking     ] GC(193) Concurrent Scan Root Regions
[0.942s][info][gc,marking     ] GC(193) Concurrent Scan Root Regions 0.003ms
[0.942s][info][gc,marking     ] GC(193) Concurrent Mark (0.942s)
[0.942s][info][gc,marking     ] GC(193) Concurrent Mark From Roots
[0.942s][info][gc,task        ] GC(193) Using 2 workers of 2 for marking
[0.942s][info][gc,start       ] GC(194) Pause Full (Allocation Failure)
[0.943s][info][gc,phases,start] GC(194) Phase 1: Mark live objects
[0.946s][info][gc,stringtable ] GC(194) Cleaned string and symbol table, strings: 3222 processed, 0 removed, symbols: 25923 processed, 0 removed
[0.946s][info][gc,phases      ] GC(194) Phase 1: Mark live objects 3.168ms
[0.946s][info][gc,phases,start] GC(194) Phase 2: Compute new object addresses
[0.946s][info][gc,phases      ] GC(194) Phase 2: Compute new object addresses 0.418ms
[0.946s][info][gc,phases,start] GC(194) Phase 3: Adjust pointers
[0.949s][info][gc,phases      ] GC(194) Phase 3: Adjust pointers 2.706ms
[0.949s][info][gc,phases,start] GC(194) Phase 4: Move objects
[0.949s][info][gc,phases      ] GC(194) Phase 4: Move objects 0.005ms
[0.949s][info][gc,task        ] GC(194) Using 8 workers of 8 to rebuild remembered set
[0.951s][info][gc,heap        ] GC(194) Eden regions: 0->0(1)
[0.951s][info][gc,heap        ] GC(194) Survivor regions: 0->0(1)
[0.951s][info][gc,heap        ] GC(194) Old regions: 10->10
[0.951s][info][gc,heap        ] GC(194) Humongous regions: 0->0
[0.951s][info][gc,metaspace   ] GC(194) Metaspace: 5993K->5993K(1056768K)
[0.951s][info][gc             ] GC(194) Pause Full (Allocation Failure) 9M->9M(10M) 8.955ms
[0.951s][info][gc,cpu         ] GC(194) User=0.01s Sys=0.00s Real=0.01s

小结

G1收集器博大精深,有待进一步实践进行深入理解研究。

doc

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

推荐阅读更多精彩内容