分代收集算法通过按对象生命周期分区处理提升GC效率:基于弱分代假说(98%新对象短命)和强分代假说(幸存对象长命),划分为年轻代(复制算法,毫秒级Minor GC)和老年代(标记-整理,避免碎片),并用记忆集优化跨代引用扫描。

基于两个关键假说,把堆内存切得合理
它不凭空设计,而是建立在被大量实践验证的两个观察上:
- 弱分代假说:98%以上的新建对象活不过第一次GC(比如临时String、循环变量、DTO实例)
- 强分代假说:能挺过几次Minor GC的对象,大概率会长期存活(比如Spring Bean、连接池、缓存容器)
因此JVM把堆划为年轻代(含Eden + 2个Survivor)和老年代,让不同寿命的对象各归其位,避免“一刀切”式扫描。
年轻代用复制算法,快得只看存活对象
年轻代区域小、对象死得多、存活少——复制算法天然适配:
- 每次Minor GC只遍历Eden和一个Survivor里的存活对象,把它们复制到另一个Survivor(或晋升老年代),其余空间直接清零
- 不用标记所有对象,也不用清理碎片,指针一挪就完成分配,毫秒级完成
- HotSpot默认Eden:Survivor = 8:1:1,90%空间可用,兼顾效率与利用率
老年代用标记-整理,稳得住长期存活对象
老年代对象多、存活率高、不能频繁停顿——复制算法在这里代价太高:
- 标记阶段识别长期存活对象,整理阶段把它们紧凑排列,既消除碎片,又保障大对象能顺利分配
- 避免像标记-清除那样留下零散空隙,导致后续分配失败触发更重的Full GC
- CMS、G1、ZGC等现代收集器虽机制不同,但底层仍延续“老年代侧重吞吐/延迟平衡”的分代逻辑
减少跨代扫描开销,GC Roots更轻量
年轻代对象可能被老年代引用(比如静态Map持有临时对象),但这类跨代引用极少:
- JVM引入记忆集(Remembered Set),只记录老年代哪些卡页(Card)修改过指向年轻代的引用
- Minor GC时只需扫描这些少量卡页,不用遍历整个老年代,大幅缩短STW时间
- 这是分代能真正落地的关键工程优化,否则理论再好也扛不住实际开销

















