连载中 8/20

经典收集器:吞吐量与停顿时间的第一次分家

2026-09-14 · 62 阅读 · 0 评论 · 0 赞

两个门派

GC 的世界有一场持续至今的分家:吞吐量优先关注总账——单位时间里干完的活最多,单次停顿长点无所谓;延迟优先关注体验——每次停顿都要短,哪怕总开销更大。批处理跑数、离线计算选前者;在线交易、面向用户的服务选后者。所有收集器都可以放进这张坐标系里看。

新生代三件套

Serial:单线程收集,收集时全停顿——简单高效没废话,客户端和小内存场景至今在用;ParNew:Serial 的多线程版,为配合 CMS 而生;Parallel Scavenge:也是多线程,但目标是可控的吞吐量,提供 -XX:MaxGCPauseMillis-XX:GCTimeRatio 两个旋钮,还支持自适应调节(GC 自动向代尺寸要空间)。JDK 8 的默认组合是 Parallel Scavenge + Parallel Old——服务端吞吐优先的务实选择。

CMS:并发收集的第一位选手

// CMS 老年代回收四阶段
// 1. 初始标记  STW,极短:只标记 GC Roots 直接关联的对象
// 2. 并发标记  与用户线程并行:沿着引用链摸完整堆(最耗时但不停顿)
// 3. 重新标记  STW,较短:修正并发期间用户线程改动的部分
// 4. 并发清除  与用户线程并行:把死对象就地清掉(标记-清除算法)
//
// 精髓:把最耗时的活儿挪到并发阶段,STW 只剩两个短环节
// 代价:并发=和业务抢 CPU;清除=留下碎片

CMS 的三宗罪

一,CPU 敏感:并发阶段默认占(核数+3)/4 的线程,核少时业务明显变慢。二,浮动垃圾:并发标记和清除期间产生的新垃圾只能等下轮,如果老年代增长太快、清理前就满了,并发模式失败(Concurrent Mode Failure),JVM 会启动保命方案——Serial Old 单线程整理整堆,一次超长 STW,比不用 CMS 还惨。缓解办法是把 -XX:CMSInitiatingOccupancyFraction(默认 92%)调低、提前触发,但调太低又浪费 GC 次数。三,碎片:标记-清除不给对象搬家,碎片积累到分配不出连续空间,只能靠 Full GC 前的压缩救场。这三宗罪注定了 CMS 的退场——JDK 9 被标记废弃,JDK 14 彻底移除。

经典组合速查

新生代老年代定位
SerialSerial Old单线程,客户端/小内存
ParNewCMS + Serial Old 兜底延迟优先(JDK 8 时代主流)
Parallel ScavengeParallel Old吞吐优先,JDK 8 默认

CMS 教会业界一件事:停顿可以并发化,但"边干活边搬家"在当时做不到——所以它只能选清除,只能留碎片。把并发化和"无碎片"同时做到的,是下一篇的主角 G1。

503

10 年全栈工程师 · 503咖啡馆主理人

#CMS收集器#Parallel#吞吐量优先#延迟优先#Concurrent Mode Failure

评论 (0)

相关推荐

连载中 12/20

排查四件套:jstack、jmap、jstat、jcmd 的实战分工

jstack 看线程在干什么,jmap 看堆里装了什么,jstat 看运行时在变什么,jcmd 是统一入口。四把刀各管一段,配合着用没有查不动的现场。

#jstack#jmap#jstat#jcmd#排查工具
2026-09-16 · 1 阅读 · 0 评论 · 0 赞
连载中 11/20

GC 日志:把回收过程翻译成人话

一行 GC 日志里塞着七种信息:谁触发的、收了哪、停了多久、活了哪些。加上 -Xlog 配置,再加上日志分析工具,GC 不再是只能盯监控曲线的黑盒。

#GC日志#Xlog#日志分析#GC监控#Full GC排查
2026-09-16 · 12 阅读 · 0 评论 · 0 赞
连载中 10/20

ZGC:亚毫秒停顿是怎么炼成的

百 G 大堆停顿不到一毫秒,靠的是把搬家全部挪到并发阶段——着色指针让引用自带状态,读屏障让搬运中的对象依然可访问。代价是吞吐与内存,收益是停顿与堆大小解耦。

#ZGC#着色指针#读屏障#亚毫秒停顿#分代ZGC
2026-09-15 · 8 阅读 · 0 评论 · 0 赞