新生代gc在eden区空间不足时触发,对象晋升依据年龄、大小及survivor容量动态决策;晋升路径包括年龄达标、大对象直接分配和动态担保失败溢出;survivor区非必经路径,g1等收集器已弱化其作用。

新生代GC(Minor GC)主要在Eden区空间不足时触发,对象晋升则取决于年龄、大小和 Survivor 区容量等多重条件,不是简单“活够次数就走”,而是 JVM 根据内存压力动态决策的过程。
Minor GC 的实际触发点
Minor GC 并非按固定时间或对象数量触发,而是由 Eden 区的可用空间决定:
- 新对象分配时,若 Eden 区剩余空间不足以容纳该对象,立即触发 Minor GC;
- 即使 Eden 区未完全填满,但连续分配大对象导致碎片化严重,也可能提前触发(尤其在开启-XX:+UseAdaptiveSizePolicy时);
- TLAB(线程本地分配缓冲区)耗尽且无法扩容时,也会回退到 Eden 公共区分配,加速 Eden 满溢,间接促发 GC。
对象晋升到老年代的三种路径
晋升不是只看“年龄15”,JVM 会根据当前内存状态选择最稳妥的路径:
- 年龄达标晋升:对象在 Survivor 区中每经历一次 Minor GC,年龄 +1;达到 -XX:MaxTenuringThreshold 设置值(默认15)后,下次 GC 时直接进入老年代;
- 大对象直接晋升:当对象大小超过 -XX:PretenureSizeThreshold(如设为1MB),JVM 会绕过 Eden,直接在老年代分配(避免在新生代反复复制);
- 动态担保晋升:Minor GC 前,JVM 检查老年代剩余空间是否足够容纳本次 GC 后所有待晋升对象;若不够,且未启用 -XX:-HandlePromotionFailure,则直接触发 Full GC;若启用该参数,JVM 会把 Survivor 放不下的存活对象全部“挤进”老年代,哪怕它们年龄还很小。
Survivor 区不是必经中转站
很多开发者误以为所有对象都必须“Eden → Survivor → 老年代”,其实 Survivor 区只是优化手段,并非强制路径:
- 对象首次创建就在 Eden,若 Minor GC 后存活,才可能进入 Survivor;
- 若某次 Minor GC 后,Survivor 区空间不足以容纳所有存活对象,JVM 会将超出部分直接送入老年代(称为“分配担保失败后的溢出晋升”);
- 某些垃圾收集器(如 G1)已弱化 Survivor 概念,改用“复制到另一块 Region”的方式,年龄阈值也变为动态估算而非固定计数。
影响晋升行为的关键参数
这些参数直接影响 Minor GC 频率与对象去向,调优时需结合业务对象生命周期:
- -Xmn:设置新生代总大小,过小会加剧 Minor GC 频率,迫使短命对象过早晋升;
- -XX:SurvivorRatio:控制 Eden 与 Survivor 空间比例(如 -XX:SurvivorRatio=8 表示 Eden 占 8 份,两个 Survivor 各占 1 份);
- -XX:MaxTenuringThreshold:最大晋升年龄,设为 0 表示对象熬过第一次 GC 就进老年代;设为 1 表示最多在 Survivor 待一轮;
- -XX:+AlwaysTenure(HotSpot 特有):关闭 Survivor 复制逻辑,所有 Minor GC 存活对象一律晋升,适合大量中生命周期对象场景。











