G1 垃圾收集器
G1 垃圾收集器
概述
G1(Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存多机器。以极高概率满足GC停顿时间要求的同时,还具备高吞吐性能特征.
分区机制
G1保留了年轻代和老年代的概念,但不再是物理隔离,而是逻辑上的概念,实现了更灵活的内存管理。

G1将Java堆划分为多个大小相等的独立区域(Region),JVM最多可以有2048个Region。如下默认计算方式:
Region = 堆内存/2048
- 例如假设对内存16G,默认2048个Region,则每个Region = 16*1024/2048 = 8M
- 当然也可以用参数XX:G1HeapRegionSize手动指定Region大小,但是推荐默认的计算方式.
分代概念
由上图可知由每个Region都可以分别代表为
- Eden
- Survivor
- Old
- Humongous
专门分配大对象,超过Region的50%,上述8M大小Region,若对象超过4M就会直接分配到Humongous
1.年轻代默认占堆内存的5%,可通过-XX:G1NewSizePercent设置初始占比
2.年轻代占比默认最多不超过60%,可通过-XX:G1MaxNewSizePercent调整
3.年轻代中的Eden和Survivor区域默认比例为8:1:1
4.一个Region可能之前是年轻代,垃圾回收后可能变成老年代,Region功能动态变化
G1收集过程

- 初始标记 (initial mark,STW)
暂停所有的其他线程,并记录下gc roots直接能引用的对象,速度很快 - 并发标记(Concurrent Marking)
根据初始标记阶段的结果,与应用线程并发地遍历整个对象图,标记出所有的存活对象 - 最终标记(Remark,STW)
暂停整个应用,修正并发标记期间状态发生变化的对象状态,使用SATB(原始快照). - 筛选回收(Cleanup,STW)
清理垃圾,该阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划.例如老年代此时有1000Region都满了,但因为根据预期停顿时间,本次垃圾回收可能只停顿200ms,那么通过之前成本计算,可能回收800个Region差不多就需要200ms,那么本次就只会回收800Region。

G1收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的Region,比如一个Region花100ms能回收10M垃圾,另外一个Region花100ms能回收20M垃圾,在回收时间有限情况下,G1会优先选择后面这个Region回收。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限时间内可以尽可能高的收集效率。
G1 垃圾收集分类
- YoungGC
YoungGC并不是说现有的Eden区放满了就会马上触发,G1会计算下现在Eden区回收大概要多久时间,如果回收时间远远小于参数 -XX:MaxGCPauseMills 设定的值,那么增加年轻代的region,继续给新对象存放,不会马上做YoungGC,直到下一次Eden区放满,G1计算回收时间接近参数 -XX:MaxGCPauseMills 设定的值,那么就会触发Young GC. - MixedGC
老年代的堆占有率达到参数(-XX:InitiatingHeapOccupancyPercent)设定的值则触发,回收所有的Young和部分Old(根据期望的GC停顿时间确定old区垃圾收集的优先顺序)以及大对象区,正常情况G1的垃圾收集是先做
MixedGC,主要使用复制算法,需要把各个region中存活的对象拷贝到别的region里去,拷贝过程中如果发现没有足够的空region能够承载拷贝对象就会触发一次Full GC. - Full GC
停止系统程序,然后采用单线程进行标记、清理和压缩整理,好空闲出来一批Region来供下一次MixedGC使用,这个过程是非常耗时的。
G1适合场景
- 50%以上的堆被存活对象占用
- 对象分配和晋升的速度变化非常大
- 垃圾回收时间特别长,超过1秒
- 8GB以上的堆内存(建议值)
- 停顿时间是500ms以内
为什么G1用SATB?CMS用增量更新?
结合CMS垃圾收集器,
- 三色标记
- 当黑色对象A一旦新插入了指向白色对象B的引用之后
1.增量更新方式将黑色对象A变为灰色.
2.SATB(原始快照)方式将白色对象直接标记为黑色. - 黑色对象不在扫描,灰色对象需要继续深度扫描。
结论:
增量更新需要在重新标记阶段再次深度扫描引用对象,CMS就一块老年代区域,而G1有更大的对象且位于不同的Region,如果使用增量更新再次深度扫描,代价会比CMS高。所以G1采用SATB(原始快照),只是简单标记,可能存在更多浮动垃圾,等待下一轮GC处理.
