# 11. Minor GC 和 Major GC(Full GC)的区别是什么?

# 标准答案

Minor GC 主要回收新生代的对象,采用复制算法,执行速度快,但可能导致对象晋升到老年代。Major GC(也称 Full GC)会回收整个堆,包括新生代和老年代,通常触发 Stop-the-World(STW),执行时间长,对应用性能影响较大。

# 答案解析

Java 垃圾回收机制根据堆的分代模型,将 GC 分为 Minor GCMajor GC(Full GC),两者在作用范围、触发条件、执行方式和性能影响方面存在明显区别。

# Minor GC(针对新生代)

  1. 作用范围:仅回收新生代(Eden + Survivor),不会影响老年代。
  2. 触发条件:Eden 区满时触发,存活对象会移动到 Survivor 或晋升到老年代。
  3. 执行方式:采用复制算法(Copying),效率高,暂停时间短。
  4. 性能影响:通常影响较小,但可能导致老年代膨胀,引发 Full GC。

示例:

// Eden 区满时会触发 Minor GC
byte[] array1 = new byte[2 * 1024 * 1024]; // 2MB
byte[] array2 = new byte[2 * 1024 * 1024]; // 2MB
1
2
3

如果 Eden 空间不足,Minor GC 会清理不可达对象,并将存活对象移入 Survivor 或老年代。

# Major GC(Full GC,回收整个堆)

  1. 作用范围:回收整个堆,包括新生代和老年代。
  2. 触发条件
    • 老年代空间不足
    • System.gc() 调用(可能触发 Full GC,但 JVM 可忽略)
    • CMS GC 执行失败(Concurrent Mode Failure)
    • G1 GC 进行 Mixed GC(涉及老年代)
  3. 执行方式:通常采用标记-清除(Mark-Sweep)或标记-整理(Mark-Compact),清理过程耗时长。
  4. 性能影响:会导致 STW(Stop-the-World),应用线程暂停,影响吞吐量和响应时间。

示例:

// System.gc() 可能会触发 Full GC
System.gc(); 
1
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 行为?