在这里插入图片描述

一次完整的 GC 流程解析(以 CMS 收集器为例)

1. 触发条件

老年代空间不足(或达到预设阈值)时触发 Full GC。例如:

  • 大对象直接进入老年代但空间不足
  • 新生代对象晋升到老年代时空间不足
  • 方法区(元空间)内存不足
  • 手动调用 System.gc()

2. 核心流程(分阶段)

打扫房间 比喻 GC 流程:

  • 房间 = JVM 堆内存
  • 垃圾 = 无引用的对象
  • 清洁工 = GC 线程
阶段 1:初始标记(Initial Mark - STW)
  • 动作:暂停所有工作(STW),快速标记 直接与 GC Roots 关联的对象(如静态变量、活动线程栈中的对象)。
  • 耗时:极短(毫秒级)。
  • 比喻:清洁工先锁定房间门口,快速标记门口显眼的垃圾袋(GC Roots 直接关联的对象)。
阶段 2:并发标记(Concurrent Mark)
  • 动作:恢复用户线程,并发遍历对象引用链,标记所有存活对象。
  • 耗时:较长(与堆大小成正比)。
  • 风险:用户线程可能修改对象引用(产生"浮动垃圾")。
  • 比喻:清洁工边打扫边允许住户进出房间,住户可能丢弃新垃圾(浮动垃圾)。
阶段 3:重新标记(Remark - STW)
  • 动作:再次暂停所有工作,修正并发标记期间的引用变化(通过增量更新/原始快照算法)。
  • 耗时:短于并发标记。
  • 比喻:二次锁定房间,检查住户新丢弃的垃圾并更新标记。
阶段 4:并发清除(Concurrent Sweep)
  • 动作:恢复用户线程,删除未被标记的对象,回收内存。
  • 耗时:较长。
  • 问题:产生内存碎片(类似房间角落残留碎屑)。
  • 比喻:边允许住户活动边清扫已标记的垃圾,但房间可能不整洁(碎片)。

3. 特殊情况处理
  • 内存碎片过多 → 触发 内存压缩(Mark-Compact):
    移动存活对象到内存一端,消除碎片(类似重新排列家具)。
  • 并发模式失败(Concurrent Mode Failure):
    当 GC 速度跟不上对象分配速度时,退化为 Serial Old 收集器(全程 STW,暂停时间更长)。

4. 总结与面试要点
关键点 说明
STW 发生阶段 初始标记、重新标记(尽量缩短暂停时间)
并发阶段 并发标记、并发清除(减少对应用影响)
浮动垃圾 并发阶段新产生的垃圾,需下次 GC 回收
适用场景 重视响应速度的系统(如 Web 服务)
缺点 内存碎片、CPU 资源争用
替代方案 G1/ZGC 收集器(解决碎片问题,可控停顿)

核心思想:CMS 通过 部分 STW + 并发操作 平衡吞吐量和延迟,适合需要低延迟的应用。
在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐