# 11. Minor GC 和 Major GC(Full GC)的区别是什么?
# 标准答案
Minor GC 主要回收新生代的对象,采用复制算法,执行速度快,但可能导致对象晋升到老年代。Major GC(也称 Full GC)会回收整个堆,包括新生代和老年代,通常触发 Stop-the-World(STW),执行时间长,对应用性能影响较大。
# 答案解析
Java 垃圾回收机制根据堆的分代模型,将 GC 分为 Minor GC 和 Major GC(Full GC),两者在作用范围、触发条件、执行方式和性能影响方面存在明显区别。
# Minor GC(针对新生代)
- 作用范围:仅回收新生代(Eden + Survivor),不会影响老年代。
- 触发条件:Eden 区满时触发,存活对象会移动到 Survivor 或晋升到老年代。
- 执行方式:采用复制算法(Copying),效率高,暂停时间短。
- 性能影响:通常影响较小,但可能导致老年代膨胀,引发 Full GC。
示例:
// Eden 区满时会触发 Minor GC
byte[] array1 = new byte[2 * 1024 * 1024]; // 2MB
byte[] array2 = new byte[2 * 1024 * 1024]; // 2MB
1
2
3
2
3
如果 Eden 空间不足,Minor GC 会清理不可达对象,并将存活对象移入 Survivor 或老年代。
# Major GC(Full GC,回收整个堆)
- 作用范围:回收整个堆,包括新生代和老年代。
- 触发条件:
- 老年代空间不足
- System.gc() 调用(可能触发 Full GC,但 JVM 可忽略)
- CMS GC 执行失败(Concurrent Mode Failure)
- G1 GC 进行 Mixed GC(涉及老年代)
- 执行方式:通常采用标记-清除(Mark-Sweep)或标记-整理(Mark-Compact),清理过程耗时长。
- 性能影响:会导致 STW(Stop-the-World),应用线程暂停,影响吞吐量和响应时间。
示例:
// System.gc() 可能会触发 Full GC
System.gc();
1
2
2
调用 System.gc()
可能导致 Full GC,但不建议使用,因为 JVM 可能会忽略这个请求。
# Minor GC vs. Major GC(Full GC)对比
对比项 | Minor GC | Major GC(Full GC) |
---|---|---|
作用范围 | 新生代(Eden + Survivor) | 整个堆(新生代 + 老年代) |
触发条件 | Eden 区满时触发 | 老年代满,调用 System.gc(),CMS 失败等 |
执行方式 | 复制算法(Copying GC) | 标记-清除(Mark-Sweep)或标记-整理(Mark-Compact) |
性能影响 | 停顿时间短,对应用影响较小 | 可能导致长时间 STW,影响应用性能 |
对象晋升 | 可能导致对象晋升到老年代 | 直接回收老年代对象 |
触发频率 | 频繁 | 相对较少 |
# 常见错误
- 误以为 Minor GC 和 Major GC 只影响各自的分区,实际上 Minor GC 可能间接影响老年代(对象晋升)。
- 误以为 System.gc() 一定触发 Full GC,实际上 JVM 可能会忽略。
- 误以为 Full GC 只是清理老年代,实际上它回收整个堆,包括新生代和老年代。
# 最佳实践
- 通过
-XX:+PrintGCDetails
监控 GC 频率,避免 Full GC 过于频繁。 - 使用 G1 GC 或 ZGC 以减少 STW 时间,提高吞吐量。
- 避免
System.gc()
,除非在特定场景下可控调用(如缓存清理)。 - 调整
-XX:NewRatio
,合理分配新生代和老年代大小,减少对象晋升到老年代的频率。
# 深入追问
- 为什么 G1 GC 采用 Mixed GC,而不是传统 Full GC?
- CMS GC 为什么可能触发 Concurrent Mode Failure?如何优化?
- ZGC 和 Shenandoah GC 如何优化 Full GC,降低 STW 时间?
# 相关面试题
- Minor GC 触发的机制是什么?为什么 Eden 满时会触发?
- CMS GC 采用什么策略避免 Full GC?为什么会导致碎片化?
- G1 GC 如何减少 Full GC 影响?Mixed GC 的作用是什么?
- 如何通过 GC 日志分析应用的 GC 行为?