cms降低停顿的核心是“不打断”而非“快”,通过初始标记、重新标记两次毫秒级stw,以及并发标记、并发清除全程与用户线程协作,实现极低延迟;代价是cpu占用高和内存碎片。

CMS收集器降低停顿时间的核心,不是靠“快”,而是靠“不打断”——它把最耗时的两个环节(标记和清除)挪到用户线程运行的同时去做,只在关键检查点做极短暂停。
初始标记和重新标记:两次短暂STW,控制在毫秒级
初始标记只处理GC Roots直接关联的对象(比如栈中引用、静态变量、JNI引用),以及被新生代存活对象引用的老年代对象。这个集合很小,JDK 8之后还改为多线程执行,通常不到1毫秒。重新标记则专门修补并发标记期间因用户线程修改引用而漏标的部分,虽然比初始标记稍长,但一般也控制在几毫秒到十几毫秒内。这两次停顿加起来,远低于传统串行或并行老年代收集器的一次完整STW(可能上百毫秒甚至秒级)。
并发标记:边跑边标,不抢CPU时间片,只借计算资源
这个阶段GC线程与用户线程真正并发运行——不是并行(不强制多核),而是在同一核上交替执行。CMS用三色标记法(黑/灰/白)配合增量更新(Incremental Update)机制,确保即使用户线程在遍历途中改了引用,也能在后续修正。它不追求一次标全,而是持续跟踪变化,把“全量分析”的压力拆解成可并发的小任务。因此,用户请求照常处理,只是响应延迟略有抬升,而非完全卡住。
并发清除:删垃圾不挪对象,全程无停顿
清除阶段只是遍历标记位图,把未被标记的内存块直接归还给空闲链表。由于不移动存活对象,不需要更新所有引用,也不涉及对象重定位,所以可以完全与用户线程并发。哪怕这时用户线程又创建了新对象(即“浮动垃圾”),CMS也不管——它只清理本轮已确认死亡的对象,把新产生的垃圾留给下一轮。这种取舍换来的是零STW的清理过程。
代价换来的低延迟:资源占用与碎片是明确妥协
并发不是免费的:CMS默认启用 (CPU核心数+3)/4 个回收线程,在4核机器上占约25% CPU资源;核心越少,占比越高,吞吐量下降越明显。同时,“标记-清除”不整理内存,长期运行后老年代易产生碎片,大对象分配失败可能触发退化为Serial Old的Full GC,反而拉长停顿。所以CMS适合对延迟敏感、有足够CPU余量、且对象生命周期相对稳定的B/S服务端场景。










