← 每日面试题 学习看板

JVM 中一次完整的 GC 流程是怎样的?

面试题/00java/03JVM/04垃圾回收(GC)基础/JVM 中一次完整的 GC 流程是怎样的?.md

面试记录 2026-09-21

题目:JVM 中一次完整的 GC 流程是怎样的?

难度:medium

标签:jvm/gc, general/knowledge, difficulty/medium

评分:⭐⭐☆☆☆(2/5)

我的回答

GC 的完整流程。GC 本质上就是垃圾的回收,前置是标记垃圾。一个对象它没有引用了,就会标记为被可被回收。首先这个先进行的是年轻代回收。一个对象,如果它能被回收,就在年轻代回收的时候回收掉。如果不能被回收,就将对象从年轻代转移到幸存者区、 Survivor 区。然后这时候它就经历了一次垃圾回收。后续第二次年轻代回收的时候,如果这个对象还存活着,它就从幸存者一区转移到幸存者二区,同步转移的还有在年轻代幸存的,还存活的区域,就整个都复制到幸存者二区。经历了反复几次。如果这个对象还存活,这个反复几次的数量可以在 CMS 的参数中调配,我记得默认是 15 次。如果这个对象还存活着,这个对象就会升级到老年代,这时候年轻代的垃圾回收已经不会对这个对象产生异常了,只有当老年代或者是方法区空间满了之后,才开始进行老年代的回收,也就是 FullGC,这时候如果它还存活,它还会像之前一样在 FullGC 中原地 FullGC 中存放,直到它被垃圾回收标记为垃圾,没有引用,进行被回收。这是常规的垃圾回收的升级换代方法。

点评

优点:

不足:

补充:

  1. 对象晋升流程:Eden 满 → Young GC → Survivor 交替 → 达阈值晋升老年代
  2. 算法执行流程:Initial Mark (STW) → Concurrent Mark → Remark (STW) → Concurrent Sweep

完整讲解

第一部分:知识重点剖析

核心考点定位:考察 GC 流程的双层理解——对象晋升路径 + 算法执行阶段,以及并发 GC 的关键环节。

知识点拆解:

  1. GC 流程的两层含义
  1. Young GC(Minor GC)完整流程
  1. 清空 Eden(不标不整理,直接归零)
  2. 将 Eden 存活对象复制到 To Survivor(复制算法)
  3. 将 From Survivor 存活对象按年龄判断:
  1. Survivor 装不下 → 空间分配担保:能塞老年代就塞,塞不下晋升失败
  2. 交换 From 和 To 指针
  3. 清空 From Survivor
  1. Full GC 完整流程(CMS 为例,G1 有 Mixed GC)
  1. Initial Mark(初始标记):STW,标 GC Roots,很快
  2. Concurrent Mark(并发标记):GC 线程 + 用户线程并发遍历,不 STW
  3. Remark(重新标记):STW,处理并发标记期间的引用变动(靠写屏障 / Card Table 缩短)
  4. Concurrent Sweep(并发清除):并发清理死对象,不 STW(有碎片)
  1. Mixed GC(G1 特有)
  1. 关键机制:写屏障 + Remembered Set
  1. 观测与调优

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. Young GC 具体动作是什么?为什么 Eden/From 直接清零?
  1. Remark 为什么需要 STW?如何缩短?
  1. G1 如何避免 Full GC?
  1. 如何在生产上观察 GC 流程?
  1. ZGC 的 GC 流程和传统 GC 有什么本质不同?

第三部分:面试者参考回答(300-600 字口语化)

面试官您好,GC 的"完整流程"其实有两层含义,我按层说。

第一层是对象晋升流程。新对象先在 Eden 分配,Eden 满触发 Young GC:Eden 里的存活对象复制到 To Survivor,From Survivor 里的对象年龄 +1 后继续留 Survivor 或晋升老年代,然后交换 From 和 To 的指针,清空 Eden 和 From。反复几次 Young GC,对象年龄累积超过 MaxTenuringThreshold(默认 15)就晋升老年代。这一步的核心是复制算法,靠 Survivor 交替避免碎片。

第二层是 GC 算法执行流程,以 CMS 为例(G1 有 Mixed GC,ZGC 无 Full GC):

  1. Initial Mark(初始标记):STW,只标 GC Roots,非常快
  2. Concurrent Mark(并发标记):GC 线程和用户线程并发遍历引用图,不 STW
  3. Remark(重新标记):STW,处理并发标记期间的引用变动,靠写屏障 + Card Table / Remembered Set 缩短范围
  4. Concurrent Sweep(并发清除):并发清理死对象,不 STW(有碎片问题)

如果是 Full GC(非并发),流程是 STW 整代标记 → 标记-整理(存活压缩到一侧)→ 清理尾部。Full GC 触发条件:老年代满、Metaspace 满、System.gc()、Survivor 晋升失败。

G1 的关键差异:用 Mixed GC(Young + 部分老年代 Region)替代 Full GC,通过 -XX:MaxGCPauseMillis 目标停顿预测要回收哪些 Region,尽量避免退化到 Full GC。

贯穿全程的机制是写屏障 + Remembered Set:老年代引用新生代对象时,写屏障在赋值时更新 Card,GC 时只处理"脏"的引用,避免全堆扫描。

生产上怎么观察? 用 -Xlog:gc* 打完整 GC 日志看 STW 时长,JFR jdk.GCPhasePause 看各阶段耗时,关注 Pause Remark 和 Full GC 频率;生产上单次 STW > 200ms 或频繁 FullGC 都应告警。

一句话总结:GC 流程 = 对象晋升(Eden → Survivor → Old)+ 算法执行(Initial Mark → Concurrent Mark → Remark → Sweep),前者决定"对象去哪",后者决定"GC 怎么算"。