外观
G1垃圾回收器
约 1304 字大约 4 分钟
2025-11-08
为啥考虑G1
首先,残酷的现实,在JDK9中已经开始废弃CMS垃圾回收器,CMS成为历史。
其次,随着云服务器的成本降低,服务器配置上升,每个应用部署的机器内存,都开始在4GB以上,CMS的垃圾回收时间无法满足,而G1的特性更加符合未来的趋势。
G1有哪些特性
- 控制GC时间
通过jvm参数-XX:MaxGCPauseMillis设置,默认是200ms可以指定每次垃圾回收的时间,G1会在设定的时间内,基于内置的 Pause Prediction Model 即停顿预测模型,尽可能回收更多的内存空间,将回收性价比最大化,花同样的时间,清楚最多的垃圾。
- 适用于大堆内存
CMS垃圾回收器,如果堆内存很大,达到4GB以上,在触发GC之前,会导致积累的内存对象过多,进而导致垃圾回收时间过长,可能原来堆内存是2GB的时候,每次Young GC需要300ms, 达到4GB后,时间翻倍达到600ms。
G1的特点恰好解决了这个问题,因为是基于GC时间来触发GC,与堆内存大小无关。
新内存布局
对比parnew + CMS的组合,将堆内存分成Eden, Survivor和老年代不太一样。G1将堆内存分成了多个大小的Region,大小区间最小1M、最大32M ,总之是2的幂次方,默认每个Region的大小为 堆内存大小/2048。当然,也可以通过jvm参数-XX:G1HeapRegionSize指定每个Region的大小。

Region分类
真的没有Eden和Survivor了吗
虽然G1将堆分成了等大小的Region,但是,并没有将Eden和Survivor这样的划分完全去掉,而是,将不同Region也分成了逻辑上的新生代和老年代,在物理内存中是不连续的,新生代中包含了Eden和Survivor。划分的区域大小不是固定的,什么意思呢?
Eden和Survivor中的Region数量实在不断的变化,G1根据算法进行分配,默认新生代Region初始占比
5%,可以通过参数-XX:G1NewSizePercent指定,最多占比60%,可以通过参数-XX:G1MaxNewSizePercent指定。分类
- Eden Region
- Survivor Region
- Old Region
- Humongous Region
存放超大对象,大小超过Region的
50%的被判定为大对象,这个和ParNew垃圾回收器中对大对象的定义逻辑不一样,不用直接进老年代,可以节约老年代的空间,避免因为老年代空间不够的GC开销。
收集集合(CSet)
CSet就是需要回收的Region集合,回收的时候,会把这些Region中存活的对象复制到空闲的Region中,然后回收掉这些Region, Young GC的CSet只包含新声代的Region,Mixed GC的CSet是包含了新声代和老年代的Region。
已记忆集合(RSet)
每个Region都有一个Rset,用来记录其他Region哪个对象引用了本Region中的对象,当进行垃圾回收的时候,就不需要扫描整个堆内存。

回收过程
G1中提供了Young GC、Mixed GC两种垃圾回收模式,这两种垃圾回收模式,都是Stop The World(STW)的。 G1已经没有fullGC概念,需要fullGC时,调用serialOld GC 进行全堆扫描(包括 eden、survivor、o、perm)。
Young GC
扫描GC Roots
跟CMS类似,Stop the world,扫描GC Roots对象(局部变量,全局变量引用的对象),从GC Roots标记Eden中直接可达的对象
复制扫描出的存活的对象到survivor2/old区
Eden区内存段中存活的对象会被复制到Survivor区中空的内存分段,Survivor区内存段中存活的对象如果年龄未达阈值,年龄会加1,达到阀值会被会被复制到old区中空的内存分段。如果Survivor空间不够,Eden空间的部分数据会直接晋升到老年代空间。
清空Region 回收Eden与已复制完的Survivor区
Mixed GC
多次 Young GC 之后,当越来越多的对象晋升到老年代old region,Old Regions慢慢累积,直到到达阈值,默认是45%,可以通过参数-XX:InitiatingHeapOccupancyPercent设置。
对Old Regions的收集会同时涉及若干个Young和Old Regions,因此被称为Mixed GC。
- 初始标记(initial mark,STW)
标记那些和GC ROOT直接连接的对象,存在STW,但是STW时间很短
- 并发标记(Concurrent Marking)
同CMS的并发标记(GC线程和业务线程同时工作,标记出来哪些是垃圾 最终标记)
- 最终标记(Remark,STW)
同CMS的重新标记(因为并发标记会造成漏标,必须重新标记,存在STW)
- 筛选回收(Cleanup,STW)
回收所有年轻代Region + 部分老年代Region ,因为这个过程中会产生STW,G1为了最大概率满足GC停顿时间的要求,会优先回收那些满足回收条件, 且STW时间不超过最大停顿时间的老年代Region。
