G1 面试高频问答 + GC时序流程 + G1日志解读
一、G1面试高频问答
Q1:讲讲G1整体设计思想?
A:G1全称Garbage‑First,面向大堆、可控STW停顿。
把Java堆切分成多个等大Region,不再物理划分新生代老年代,Region动态承担Eden/Survivor/Old/Humongous角色。
核心思路:统计每个Region垃圾占比,优先回收垃圾最多的Region;以复制疏散算法回收,解决CMS内存碎片;通过MaxGCPauseMillis控制单次GC目标停顿,做到可预测延迟。
Q2:Region有哪几种?Humongous巨型对象规则?
A:
- Eden、Survivor、Old、Humongous巨型区
- 对象大小 > 1/2 RegionSize,直接作为巨型对象,分配Humongous Region,不进Eden。
- JDK8:巨型对象默认只有FullGC回收;JDK8u40之后YGC可以回收死亡巨型对象。
坑:大量短命大对象,会造成Humongous堆积,频繁FullGC。
Q3:什么是RSet记忆集?解决什么问题?底层如何实现?
A:
问题背景:回收某个Region,如果扫描整个堆找引用,开销爆炸。
- RSet(Remembered Set):每个Region维护,记录其他Region指向本Region的跨Region引用。YGC/MixedGC只扫描RSet,不用扫描全部老年代。
- 底层依赖Card Table卡表,512字节一张卡;写屏障拦截引用赋值,标记脏卡,异步更新RSet。
- 代价:额外占用堆内存 5%‑20%,带来CPU开销。
Q4:CSet是什么?
A:Collection Set收集集合,本次GC要回收的Region集合。
G1根据目标停顿时间,挑选一批高垃圾收益Region放入CSet;YoungGC的CSet是全部Eden;MixedGC的CSet = Eden + 部分Old高收益Region。
Q5:讲完整并发标记周期流程(5阶段)
A:触发条件:老年代占堆达到 IHOP -XX:InitiatingHeapOccupancyPercent=45
- Initial‑Mark初始标记【STW】:标记GC Roots直接可达对象,依附在一次YGC末尾,停顿很短。
- Root Region Scanning根分区扫描【并发】:扫描Survivor里晋升对象作为根;必须在下一次YGC前完成,否则YGC等待。
- Concurrent Mark并发标记【业务线程并发运行】:遍历对象图,使用SATB快照写屏障标记存活对象。
- Remark重新标记【STW】:处理SATB缓冲区、RSet变动,完成存活标记。
- Cleanup清理阶段【部分STW】:统计每个Region存活占比,释放完全空Region,生成待回收候选Region列表;此阶段不做对象复制。
并发标记周期结束之后,才会执行MixedGC分批回收老年代。
Q6:SATB快照写屏障原理,对比CMS增量更新?
A:
- G1使用SATB(Snapshot‑At‑The‑Beginning):在并发标记开始瞬间给堆打快照。
- 如果业务线程把对象引用置null,写屏障把旧引用压入SATB Buffer,防止漏标;Remark阶段只扫描SATB缓冲区,STW时间短。
- 代价:产生少量浮动垃圾,浮动垃圾本轮不回收,留给下一次GC。
对比CMS增量更新:
- CMS记录新增引用,Remark要扫描整个老年代,STW更长;浮动垃圾更少。
G1牺牲少量浮动垃圾换取更短的Remark停顿。
Q7:什么是MixedGC?和YoungGC区别?
A:
- YoungGC:只回收Eden+Survivor,不碰老年代。
- MixedGC是G1特有:同时回收新生代 + 一批高垃圾收益老年代Region。
受MaxGCPauseMillis约束,一次不会回收全部老年代,分多轮回收(G1MixedGCCountTarget默认8轮),逐步降低老年代占用。
Q8:Evacuation Failure疏散失败是什么?如何产生?怎么解决?
A:
MixedGC做对象复制疏散时,找不到足够空闲Region存放复制后的存活对象,就是疏散失败。
直接退化为单线程FullGC(JDK8),STW时间暴涨。
产生原因:
- 并发标记启动太晚,老年代增长太快,MixedGC回收跟不上对象分配速度;
- 预留内存不足;
- Humongous大对象占满堆。
解决方案:
- 调低IHOP,更早启动并发标记;
- 调高
G1ReservePercent,增加预留空闲内存; - 调大堆内存;
- 排查短命巨型对象,优化业务避免大量短生命周期大对象。
Q9:G1什么时候触发FullGC?JDK8和JDK10 FullGC差异?
触发条件:
- EvacuationFailure疏散失败;
- Humongous对象找不到连续Region;
- 元空间OOM;
- MixedGC回收速度跟不上内存分配。
差异:
- JDK8:FullGC单线程标记整理,STW极长。
- JDK10+:FullGC支持多线程,但依然是全堆压缩,开销依旧很大,生产尽量避免。
Q10:G1优缺点,适用场景,和CMS/ZGC对比?
✅优点
- 可控STW,软实时;
- 复制疏散,大幅缓解内存碎片;
- 增量局部回收,不需要整堆扫描。
❌缺点
- RSet、写屏障带来CPU、内存额外开销;
- 堆<4G吞吐量不如ParallelGC;
- Humongous坑多;依然可能FullGC。
适用:堆4~32GB,追求延迟与吞吐量折中,JDK9默认GC。
| 收集器 | 核心 | 停顿 | 适用堆 |
|---|---|---|---|
| ParallelGC | 吞吐量优先 | 长STW | <4G |
| CMS | 标记清除,碎片问题 | 中等停顿 | 4‑8G,JDK14废弃 |
| G1 | 分区复制疏散 | 可控STW | 4‑32G,折中选择 |
| ZGC | 染色指针读屏障 | 亚毫秒 | >16G,低延迟优先 |
Q11:G1关键参数有哪些?
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200 # 目标停顿,不是硬约束
-XX:InitiatingHeapOccupancyPercent=45 # IHOP,老年代占比触发并发标记
-XX:G1ReservePercent=10 # 预留内存,防止疏散失败
-XX:ConcGCThreads=N # 并发标记线程数
-XX:ParallelGCThreads=N # STW阶段并行GC线程
Q12:G1调优核心思路?
- 不要迷信MaxGCPauseMillis,它只是目标,不能保证;
- 优先规避EvacuationFailure、Humongous大对象;
- IHOP不要设置过大,避免并发标记启动太晚;
- 观察GC日志,看MixedGC是否能跟上内存分配;
- 如果频繁FullGC,优先排查业务对象问题,而不是一味调参数。
二、G1完整GC时序流程图(文本版,可复制到markdown画图工具)
业务线程持续分配对象
↓
Eden占满 → 【Young GC(STW)】
├─初始标记 Initial‑Mark(STW,依附YGC末尾)
└─正常YGC:复制Eden存活对象到Survivor,部分对象晋升Old
老年代占用达到 IHOP阈值45% → 启动【并发标记周期】
↓
1. Initial‑Mark(STW)
↓
2. Root Region Scanning(并发,业务线程运行)
↓
3. Concurrent Mark(并发标记,SATB写屏障,业务线程并行)
↓
4. Remark(STW,处理SATB Buffer + RSet)
↓
5. Cleanup(部分STW,统计Region,释放空Region,生成候选Old列表)
↓
并发标记周期完成
↓
循环执行多轮【MixedGC(STW)】
CSet = Eden + 部分高收益Old Region,复制疏散存活对象
直到老年代占用下降到安全水位
↓
回到普通YoungGC循环
⚠️ 分配过快 / 内存不足 → EvacuationFailure → FullGC(STW全堆整理)
三、G1 GC日志解读(JDK8日志,-XX:+PrintGCDetails)
1)YoungGC日志示例
GC (G1 Young Generation)
[Eden: 1024M(1024M)->0.0B(1024M) Survivors:128M->128M Heap:2048M(4096M)->900M(4096M)]
[Times: user=2.3s sys=0.1s, real=0.20s]
解读:
- G1 Young Generation:普通新生代GC,只回收Eden
- Eden:用完全部回收清空;Survivor大小变化;Heap堆总占用变化
- real=0.20s:实际STW停顿时间,重点关注
2)并发标记周期日志关键字段
GC (Initial Mark) # 初始标记,依附YGC
GC (Concurrent Mark Start)
GC (Concurrent Mark End)
GC (Remark) # 重新标记STW,关注real时间
GC (Cleanup)
出现以上日志,代表正在跑老年代并发标记周期。
3)MixedGC日志
GC (G1 Mixed Generation)
[Eden:800M->0B(800M) Survivors:100M->100M Heap:2800M(4096M)->1600M(4096M)]
[Times: user=3.0s sys=0.2s, real=0.25s]
G1 Mixed Generation:MixedGC,回收Eden+部分老年代Region。- 如果MixedGC之后堆占用下降很少:说明选中的Old Region存活对象很高,回收收益低,需要调优
G1MixedGCLiveThresholdPercent。
4)Evacuation Failure(疏散失败高危信号)
日志出现关键词:
to‑space overflow
复制对象时to‑space空间不足,即将触发FullGC,生产告警点。
5)FullGC日志
Full GC (Allocation Failure)
[Times: user=12.0s sys=0.5s, real=8.0s]
real=8秒,严重STW,必须排查根因。
6)Humongous巨型对象日志
日志出现 Humongous,代表分配巨型对象,大量出现需要业务优化。
日志排查速查表
| 日志现象 | 问题指向 |
|---|---|
| MixedGC之后堆几乎不下降 | MixedGC回收的Old Region存活太高,调参优化 |
| to‑space overflow | 疏散失败前兆,调高G1ReservePercent,调低IHOP |
| 频繁Humongous分配 | 业务产生大量>1/2RegionSize大对象 |
| Remark real时间持续高 | RSet、SATB缓冲区压力大,跨Region引用多 |
| FullGC频繁 | 内存不足 / IHOP太大 / 短命巨型对象 |
如果你需要,我可以输出ZGC面试问答版本,或者G1调优排查实战案例。

浙公网安备 33010602011771号