对象晋升老年代取决于年龄阈值、动态年龄判定和Survivor空间是否充足:年龄达-XX:MaxTenuringThreshold(默认15)时晋升;若Survivor中累计某年龄及以上对象超目标比例(默认50%),则该年龄起全部晋升;Survivor空间不足时,无论年龄大小均强制晋升。

长期存活的对象晋升老年代,核心不是“等时间”,而是靠JVM在每次Minor GC时根据对象的存活轮次(年龄)和Survivor区使用情况动态判断。它本质上是分代假设的落地:活过几轮还稳住,就大概率会长期存在,该挪去更稳定的老年代了。
对象年龄增长机制
新对象默认分配在Eden区,年龄为0。每次Minor GC后:
- Eden中存活的对象 + 当前From Survivor中仍存活的对象,一起复制到To Survivor区;
- 每成功经历一次Minor GC且存活下来,对象头中的年龄计数器就+1;
- 这个年龄是4位二进制,所以最大值是15,无法超过。
年龄达标即晋升(最直观路径)
当对象年龄达到-XX:MaxTenuringThreshold设定的阈值(默认15),下一次Minor GC时就会直接进入老年代。
- 例如设置-XX:MaxTenuringThreshold=6,那么活过6次Minor GC的对象,在第7次GC时就会晋升;
- 注意:这不是“满6岁才走”,而是“第7次GC执行时走”——晋升动作发生在GC过程中,不是年龄一到就立刻移动。
动态年龄判定(更常见、更敏感)
JVM不会死守15这个数字。它会实时统计Survivor中各年龄段对象的大小占比:
- 从年龄1开始累加同龄对象总大小;
- 一旦累计值超过Survivor容量 × -XX:TargetSurvivorRatio(默认50%),则所有≥该年龄的对象全部晋升;
- 比如age1占42%,age2占15%,累计57% > 50%,那么下次GC时age2及以上对象全进老年代;
- 这个动态计算出的新阈值会写在GC日志里,如new threshold 2 (max 15)。
Survivor空间不足时强制晋升(现实中最易触发)
Minor GC后,存活对象要整体搬进To Survivor区。但如果To区装不下:
- 不管年龄多小,超出部分直接进老年代——这就是“分配担保”;
- 常见于突发流量场景(如秒杀、批量导入),大量对象同时存活,瞬间压垮Survivor;
- 此时即使对象才1岁、2岁,也会被迫提前晋升,成为老年代“短命客”,可能加速Full GC。

















