分代收集基于对象生命周期规律设计:年轻代用复制算法高效回收短命对象,老年代用标记-整理算法稳妥处理长寿对象,并通过记忆集优化跨代引用扫描,其根基是弱分代与强分代两大实证假说。

分代收集不是靠“更高级”的算法堆砌,而是用对象真实的生命周期规律来设计回收策略——把合适的人,放在合适的岗位上。
按寿命分区:年轻代专收“短命鬼”
观察发现,98%的新建对象活不过第一次 GC(比如方法内临时字符串、循环里的 DTO)。年轻代就专管这类对象:
- 空间小、对象多、死亡率高 → 用复制算法最划算:只搬运存活对象,清空即完成,毫秒级停顿
- Eden 区占 80%,两个 Survivor 各占 10%,一次 Minor GC 只扫描 Eden + 一个 Survivor,不用遍历全堆
- 对象在 Survivor 区每熬过一次 GC,年龄 +1;默认到 15 岁(或 Survivor 空间不足)就晋升老年代
老年代稳住“长寿户”:避免频繁大扫除
能活过多次 Minor GC 的对象,大概率会长期存在(如 Spring Bean、连接池、全局缓存)。老年代不追求快,而求稳和可持续:
- 对象多、存活率高 → 复制算法代价太大(要搬动大量存活对象),改用标记-整理:先标出谁还活着,再往一端紧凑排列,清掉尾巴
- 这样既消除碎片,又保证后续大对象能顺利分配,避免因空间不连续触发更重的 Full GC
- CMS、G1、ZGC 等现代收集器虽机制不同,但对老年代的处理逻辑仍延续这一思路:侧重吞吐与延迟的平衡
跨代引用不硬扫:用记忆集减负
老年代对象可能持有年轻代对象的引用(比如静态 Map 缓存了刚创建的 DTO),但这类引用极少。硬扫整个老年代找“谁指向年轻代”,太浪费:
- JVM 引入记忆集(Remembered Set),只记录老年代中哪些“卡页(Card)”修改过跨代引用
- Minor GC 时,只需扫描这些少量卡页里的引用,不用翻遍整个老年代,STW 时间大幅缩短
- 这是分代策略能落地的关键工程优化,否则理论再好也扛不住实际开销
不靠猜,靠实证:两个假说是根基
分代不是拍脑袋划分,而是建立在被海量应用反复验证的两个观察上:
- 弱分代假说:绝大多数新对象朝生夕灭
- 强分代假说:能挺过几次 Minor GC 的对象,往往会长期存活
正是这两个朴素但扎实的规律,让 JVM 把堆切得合理,让 GC 不是“一刀切”,而是“各尽其用”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











