type
status
date
slug
summary
tags
category
icon
password
原文
G1
- 软实时、低延时、可设定目标
- JDK9+默认的 GC
- 适用于较大的堆(> 4~6G)
- 用于替代 CMS
可设置最大的 STW 停顿时间(可设定目标)
—XX:MaxGCPauseMillis
= Ndefault: 250ms
年轻代 GC 算法
- STW、Parallel 、Copying
老年代 GC 算法
- Mostly-concurrent marking(vs CMS)
- Incremental compaction
最大特征将大空间分成若干小区域,能实现一些更复杂、更精细的功能。
将堆分成若干个等大的区域
- -XX:G1HeapRegionSize=N (默认值2048)
每个Region 不再是固定的新生代、老年代这样
G1的内存布局
分区(Heap Region ,HR)
G1 的每一个分区都对应一个分区类型。
- 自由分区(Free Heap Region,FHR)
- 新生代分区(Young Heap Region,YHR)
- Eden
- Survivor
- 大对象分区(Humongous Heap Region,HHR)
- 大对象头分区
- 大对象连续分区
- 老生代分区(Old Heap Region,OHR)
自由分区问题
有的资料会说分区类型是新生代、老年代、大对象 三个分区类型。关于自由分区的时网上查询的资料有冲突。根据源码的描述,FreeTag =0 是不是对应着自由分区。
HeapRegionType源码
Region 大小和数量
Region 的大小只能为1MB、2MB、4MB、8MB、16MB和32M(jdk 版本不同可能不一样)。如果不是,则会向下取到最接近的值。例如设置 31 则会向下取整 16。
分区默认的大小最小值为1MB,最大值为 32MB。也就是说堆的最大内存为 32 * 2048 = 64GB。
大对象:大于等于分区的一半就会放到 H 区(大对象分区)
在不指定HR大小的时候,由G1启发式地推断HR大小。
-XX:G1HeapRegionSize=N 设置 Region 大小
在实际应用中,不建议设置该参数。设置固定大小,会使G1 的自动调节失效。
Region最大值计算: 2048为默认的分区个数
Region的数量 = 堆大小/Region_size
跨代/Region引用

G1的三种垃圾回收方式
新生代回收(YGC): 只回收新生代区域,代价低/频率高
混合回收(MixGC): 回收全部新生代+部分老年代,频率一般。
老年代占据堆空间超过 45% 会触发。这个命名只有G1 才有。
完全回收(FullGC): 全部堆空间,代价高/频率低,系统距离奔溃不远了
YGC 过程
什么时候触发
当内存分配的时候,剩余的空间不能满足要分配的对象时就会优先触发YGC。
YGC 过程
STW(Evacuation Pause)
- 构建 CS(Eden+Survivor)
- 扫描 GC Roots
- Update RS: 排空 Dirty Card Queue
- Process RS: 找到被哪些那些老年代对象引用
- Object Copy
- Reference Processing
G1记录每个阶段的时间,用于自动调优。
记录 Eden/Survivor的数量和 GC 时间
- 根据暂停目标自动调整 Region 的数量
- 暂停目标越短,Eden 数量越少
G1 可以设定目标时间,如果设置时间过短,它将处理的 Region 减少。
- -XX:+PrintAdaptiveSizePolicy
用 “自适应大小调整策略” 的日志输出。
- -XX:+PrintTenuringDistribution
打印对象的 “存活年龄分布” 信息,主要针对年轻代的对象。
MixedGC
新生代+部分老年代一起回收,这就是混合回收。
正常情况下,新生代全部能回收,老年代会回收一部分
STW, Parallel, Copying
混合回收什么时候发生?
在 YGC 之后,已分配内存超过内存总容量的 45% 会触发。参数是-XX:InitiatingHeapOccupancyPercent
混合回收、Full GC 都是同时处理新生代和老年代。
对象什么时候进入老年代
Eden 区的对象满足以下条件会进入老年代
- 如果一些对象经过几轮 YGC 仍然存活,或者触发了动态年龄判断规则
- 或者存活的对象在 S 区放不下了,都会让对象进入老年代
- 大对象直接进入单独的大对象 Region,但是大对象区域本身就占用的是老年代区域
哪些 Region 会被回收
关于 Collect Set:
MixedGC 包含了新生代所有分区和老年代部分分区
是否要放入 CSet: XX:G1MixedGCLiveThresholdPercent,默认为 85% 即 “存活对象占比 ≤ 15%” 的老年代 Region 会被优先选中(垃圾越多,回收价值越高)。
YGC与MixedGC 是什么关系
YGC 是 MixedGC的前奏,YGC 完成,就代表 mixedGC已经完成了初始化标记阶段,YGC已经帮 MixedGC已经帮 MixedGC干完了初始化的活。
MixedGC之前一定先进行一次YGC
MixedGC是否会真的执行
执行条件:XX:G1HeapWastePercent 默认5%。也就是说可回收的空间占总空间的比例大于5%才会启动 MixedGC。否则即使并发标记已经完成也不执行。
并发标记以后,发现回收的价值不高,就不执行。
MixedGC回收会多次执行
停顿时间:
根据其他条件计算出 CSet里有 400 个 Region满足回收的条件,但是根据停顿时间一次只能回收 50 个,怎么办?
分成多次,一次完成 50 个,8 次搞定
XX:G1MixedGCCountTarget 默认为 8即 MixedGC对 CSet 分配回收,最多分成 8次。
MixedGC过程
- 初始标记阶段(STW)
标记出所有由 GCRoot 等直接引用的对象,会暂停用户程序运行
- 并发标记阶段
标记上一步中标记的所有引用对象 ,执行时间略长。用户程序也会同时执行,不会 STW。
在并发标记对象的引用关系可能存在变更。
- 再标记阶段
标记出上一个阶段没有被标记的对象,会 STW,执行速度非常快(影响小)
- 存活对象计数阶段
统计出每个 Region 存活对象的数量
- 垃圾回收阶段
选择回收价值较高的区域,把存活对象复制到新分区。
Full GC
什么时候触发 Full GC
YGC和 MixedGC都不够(无法分配对象)触发 Full GC
永久代满了也会触发 Full GC
Full GC是危险的
Full GC可能进行两次,第二次是回收软引用,如果对象仍然无法分配,系统基本要 OOM 了。
Full GC 如何复制对象
Full GC使用”标记-压缩“(因为没有 Region 可以使用复制了),时间更慢,代价更高。
Full GC的过程
- 标记活跃对象,然后计算对象的新地址
Full GC时,进入标记阶段,标记所有的存活对象,这个过程与 YGC MixedGC基本类似。
- 更新引用对象的地址
逐个遍历每个 Region,每个 Region 从头开始,找到存活的对象指向接下来被回收的新位置。
Region 里的对象之间可能也有引用关系,这里还要将 Region 内的对象的引用指向新的位置。
- 移动对象完成压缩
复制对象,将对象复制到新位置上,完成压缩。
- 后处理
- 尝试调整整个堆空间的大小
- 遍历堆,重构 RSet,Region 里的对象都发生了变化。
- 清除dirty Card队列,并把所有的分区都认为是old分区。
- 记录各种信息,
G1 停顿预测模型
G1 是一个响应时间优先的 GC 算法,用户可以设定整个 GC 过程的期望停顿时间,由参数 MaxGCpauseMillis 控制,默认值200MS。
这里的期望停顿时间不是硬性他条件,G1会努力在这个目标停顿时间内完成垃圾回收的工作,但是它不能保证,即也不可能完成(设置了太小的停顿时间,新生代太大等)
G1 的预测逻辑是基于衰减平均值和衰减标准差
衰减平均值: 给比较近的数据更高的权重,而不是简单的平均。
停顿时间太小可能产生的问题
CardTable & Remebered Set
GC 最早引入卡表的目的是为了对内存的引用关系做标记,从而根据引用关系快速遍历活跃对象。
CardTable
- 表中的每个 entry 覆盖 512 Byte 的内存空间
- 当对应的内存空间发生改变时,标记为 dirty
RemeberedSet
- 指向 Card Table中的对应 entry
- 可找到具体内存区域
空间换时间
- 用额外的空间维护引用信息
- 5%~10% memory overhead
正个堆内存的 5%~10% 用于存储额外的空间维护引用信息

Remebered Set:用于 记录指向当前 Region 的外部引用,每个Region 都有一个专属的 RS,当 GC 收集某个 Region 时,只需扫描其 RS 即可获取所有外部引用,无需扫描整个堆。
- Author:newrain-zh
- URL:https://alex.sh.cn/article/g1
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!