晋升由年龄阈值、空间占比和大对象直入三机制决定:默认年龄阈值15但动态计算更小值;Survivor空间不足时强制晋升;超-XX:PretenureSizeThreshold的大对象直接分配至老年代。

“晋升”指新生代中存活的对象被移动到老年代的过程,不是按固定次数硬性执行,而是由两个核心机制共同决定:年龄阈值和动态空间占比规则。
年龄阈值:默认15次,但可能提前
每次Minor GC后仍存活的对象,年龄加1。当年龄达到-XX:MaxTenuringThreshold设定的阈值(HotSpot默认为15),就具备晋升资格。但注意:这只是一个上限,实际晋升年龄往往更低。
- 虚拟机会动态计算更合理的晋升年龄——遍历所有Survivor区中各年龄段对象的总大小,累加直到超过Survivor区容量的一半(由-XX:TargetSurvivorRatio控制,默认50%)
- 例如:Survivor区共10MB,1岁对象占2MB、2岁占1MB、3岁占4MB;累加到3岁时已达7MB > 5MB(一半),则晋升年龄阈值自动设为3
- 最终取“动态计算值”和“MaxTenuringThreshold”中的较小者
空间占比触发:Survivor区装不下,被迫晋升
Minor GC时,若存活对象总量超出To Survivor区可用空间,多余部分会直接晋升老年代——这叫“担保失败(Promotion Failure)前的提前晋升”,与年龄无关。
- 常见于Survivor区过小(如-XX:SurvivorRatio设得过大)、或某次GC后大量对象意外存活
- 即使对象年龄才1或2,只要Survivor放不下,就会立刻进老年代
- 这种晋升不经过年龄判断,是空间压力驱动的紧急行为
大对象直入老年代:绕过新生代
若对象体积超过-XX:PretenureSizeThreshold(默认0,即禁用),JVM会跳过Eden区,直接在老年代分配。
- 典型如长字符串、大数组、缓存块等
- 这类对象从诞生起就属于老年代,不参与年龄计数,也不走Survivor复制流程
晋升不是“满多少次就一定走”,而是看Survivor是否装得下、年龄是否达标、对象本身是否够大——三者满足其一即可发生。

















