cms 的低停顿靠“不打断”而非“快”,仅在初始标记和重新标记两处做毫秒级 stw,其余阶段并发执行;初始标记只扫根和跨代引用,耗时几毫秒;并发标记用三色标记+增量更新边运行边标记;重新标记聚焦脏卡区域精准修正漏标;并发清除零 stw,仅归还未标记内存块。

CMS 的低停顿不是靠“快”,而是靠“不打断”——它把最耗时的标记和清除动作挪到业务线程运行的同时去做,只在两个关键点做极短暂停。
初始标记:只扫根和跨代引用,毫秒级 STW
这个阶段只标记两类对象:一是 GC Roots 直接引用的老年代对象(比如栈中变量、静态字段、JNI 引用),二是新生代存活对象所引用的老年代对象。它不递归遍历,也不扫描整个老年代,所以哪怕堆很大,也只需几毫秒。JDK 8+ 默认多线程执行,可通过 -XX:+CMSParallelInitialMarkEnabled 显式控制。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
并发标记:边跑边标,靠三色标记+增量更新防漏标
- 从初始标记结果出发,遍历所有可达对象并打标记,全程与用户线程并发
- 采用三色标记法(白→灰→黑)配合增量更新(Incremental Update):一旦业务线程修改引用(如 A.ref = B → A.ref = C),就立即在对应卡表(Card Table)中标记为“脏”,后续重新标记阶段只处理这些脏卡区域
- 不追求一次标全,而是持续跟踪变化,把压力拆解成可并发的小任务
重新标记:聚焦脏卡,修正并发期间的引用变动
这是第二次 STW,但时间可控。它不重新扫描全堆,而是重点扫描三类区域:年轻代存活对象、GC Roots、以及并发标记阶段被标记为“脏”的卡页。这样能精准修补漏标,通常几毫秒到十几毫秒,远低于传统老年代 GC 的百毫秒级停顿。
并发清除:删垃圾不挪对象,真正零 STW
- 仅遍历标记位图,把未标记的内存块直接归还空闲链表
- 不移动存活对象,因此无需更新所有引用,也不涉及重定位
- 清除过程中新产生的垃圾(浮动垃圾)本次不管,留给下一轮处理
- 因完全不抢锁、不阻塞分配,所以用户线程照常分配对象,无感知
CMS 的代价很明确:CPU 占用升高(默认启用 (CPU核心数+3)/4 个回收线程)、内存碎片累积、无法处理浮动垃圾过多导致的 Concurrent Mode Failure。它适合对延迟敏感、有足够 CPU 余量、且对象生命周期较稳定的 Web 服务场景。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










