分代收集理论是JVM垃圾回收的核心设计思想,依据对象生命周期差异将堆划分为年轻代和老年代:年轻代用复制算法(Eden+S0/S1,8:1:1)快速回收短命对象,存活对象达年龄阈值或Survivor空间不足时晋升;老年代用标记-整理算法处理长期存活对象,避免碎片;通过年龄阈值、动态年龄判定和空间分配担保机制保障安全晋升,防止promotion failure。

分代收集理论是JVM垃圾回收机制的核心设计思想,它不靠统一策略“一锅端”,而是根据对象生命周期差异,把堆内存划开、算法配对、回收节奏错开,从而在吞吐、延迟和内存利用率之间取得实际可落地的平衡。
年轻代:用复制算法快速清理短命对象
年轻代专收“朝生暮死”的对象,比如方法内临时创建的String、包装类、局部集合等。HotSpot默认按8:1:1比例划分为Eden区和两个Survivor区(S0/S1)。新对象一律分配在Eden;Eden满时触发Minor GC,仅扫描Eden+S0(或S1),将存活对象复制到空的Survivor区,并按年龄计数(每过一次Minor GC年龄+1);达到阈值(默认15,可通过-XX:MaxTenuringThreshold调整)或Survivor空间不足时,对象直接晋升至老年代。
- 复制算法优势明显:只与存活对象数量相关,停顿时间短、执行快、无碎片
- Survivor区双缓冲设计缓解了原始复制算法“浪费一半空间”的缺陷
- 频繁Minor GC本身是正常现象,不代表系统异常,但若频率突增,需排查是否创建了过多临时对象或Survivor过小
老年代:用标记-整理兼顾存活率与空间连续性
老年代存放长期存活的对象,如缓存容器、连接池实例、Spring单例Bean等。这里对象密度高、存活率高,复制算法代价过大,因此采用标记-清除+标记-整理组合策略。以CMS(已弃用)或G1/Serial Old/ZGC为代表:先标记所有可达对象,再清除不可达对象;为避免内存碎片影响大对象分配,后续会触发整理(Compact),把存活对象向一端压缩,腾出大块连续空间。
- 老年代GC(即Major GC或Full GC)代价远高于Minor GC,应尽量避免频繁发生
- 触发条件包括:老年代空间不足、Minor GC后晋升失败(Promotion Failure)、元空间/直接内存溢出等
- 合理设置-Xms与-Xmx相等、避免动态扩容,可减少因空间震荡引发的老年代GC
分代协作的关键机制:晋升与担保
对象不是永远待在年轻代。能否顺利晋升,直接影响老年代压力。JVM通过多种机制保障分代边界可控:
- 年龄阈值晋升:对象在Survivor间来回复制达到设定年龄后进入老年代
- 动态年龄判定:并非机械计数,当某次Minor GC后,Survivor中累计大小≥Survivor总空间50%的年龄最小对象,会直接晋升
- 空间分配担保:Minor GC前,JVM检查老年代剩余空间是否≥年轻代全部对象总和。若不满足,且允许担保失败,则尝试进行一次Full GC;否则直接Full GC——这是避免晋升失败(promotion failure)的关键防线
现代回收器如何延续分代思想
虽然ZGC、Shenandoah主打低延迟且逻辑上不分代,但HotSpot主流生产环境仍高度依赖分代模型。G1虽将堆划分为Region,但仍按对象年龄逻辑将Region归类为Eden、Survivor或Old,并在Mixed GC阶段有选择地回收包含大量垃圾的老年代Region。这意味着:分代不是物理分区,而是一种行为抽象——只要对象存在“年轻”与“年老”的事实差异,分代思想就依然有效。
理解分代不是为了背概念,而是帮你在调优时看清问题源头:是Eden太小导致Minor GC太密?是Survivor太小加速晋升?还是老年代碎片多引发频繁Full GC?抓住代际边界,就握住了JVM内存行为的主脉络。

















