java垃圾收集器面试重在理解设计目标与适用场景:分代模型基于弱分代假说,主流收集器如serial、parallel、g1、zgc等各具取舍;调优需分析gc日志定位根因并验证改进;新版本趋势是g1→zgc,默认启用逐步演进。

Java垃圾收集器是面试高频考点,重点不在背参数,而在理解不同GC的设计目标、适用场景和关键取舍。
分代模型是理解所有GC的基础
HotSpot虚拟机默认采用分代收集思想:堆内存划分为新生代(Eden + Survivor)和老年代。对象优先在Eden分配,经历多次Minor GC后存活对象进入Survivor区,达到一定年龄(默认15)或Survivor空间不足时晋升老年代。这种划分源于“弱分代假说”——绝大多数对象朝生暮死。理解这个前提,才能看懂为什么G1要打破分代边界、ZGC为何不设分代结构。
主流收集器的核心差异与典型搭配
每种收集器解决的问题不同,没有“最好”,只有“最合适”:
- Serial / Serial Old:单线程,简单高效,适用于Client模式或小内存桌面应用;停顿时间可控但无法利用多核。
- Parallel Scavenge + Parallel Old:吞吐量优先,适合后台计算型服务;可通过-XX:MaxGCPauseMillis等参数调节吞吐与停顿的平衡。
- CMS(已废弃):以低停顿为目标,使用标记-清除算法,存在并发失败和浮动垃圾问题;JDK 14起彻底移除。
- G1:面向服务端大堆(4GB+),兼顾吞吐与响应,将堆划分为Region,通过预测模型选择回收价值高的区域;需关注-XX:MaxGCPauseMillis设定是否合理、是否出现Full GC或疏散失败(Evacuation Failure)。
- ZGC / Shenandoah:超低延迟(毫秒级STW),基于染色指针/读屏障实现并发标记与转移;ZGC要求JDK 11+且64位Linux,对堆大小无硬限制,但需注意初始堆不宜过小(建议≥8GB)。
调优不是调参数,而是分析行为
面试常问“如何排查GC问题”,关键在于建立分析闭环:
- 开启基础日志:-Xlog:gc*:file=gc.log:time,tags,level -Xlog:safepoint
- 观察频率与耗时:Minor GC是否太频繁?老年代增长是否异常?是否存在长时间Full GC?
- 定位根因:内存泄漏(对象无法被回收)、内存碎片(CMS/G1晋升失败)、分配速率过高(Eden区太小)、大对象直接进老年代(-XX:PretenureSizeThreshold)等。
- 验证改进:调整新生代比例(-XX:NewRatio)、Survivor区大小(-XX:SurvivorRatio)、最大停顿目标(G1的-XX:MaxGCPauseMillis)后,必须重跑压测对比日志。
新版本趋势与常见误区
JDK演进中GC策略持续简化:
- JDK 9起默认使用G1;JDK 17+推荐ZGC(生产可用);JDK 21默认启用ZGC(Linux x64)。
- 不要盲目追求低延迟:ZGC虽STW短,但CPU开销略高,小规模应用可能得不偿失。
- 避免混淆概念:“并发收集”不等于“无停顿”(ZGC仍有极短STW),“增量式”不等于“实时”(CMS仍会Stop-The-World)。
- 年轻代GC永远有STW,真正可优化的是老年代回收方式和触发时机。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











