对象晋升是严格依赖堆内存物理分区的硬性流转链路:起点为eden区(唯一新生对象分配地),经survivor区计龄缓冲,满足年龄阈值、动态年龄或空间担保任一条件才晋升老年代;大对象可直通老年代但受限于参数与gc类型。

直接看堆内存的物理分区,对象晋升就不是抽象概念——它是一条有起点、有路径、有门槛、有终点的硬性流转链路。关键不在“怎么晋升”,而在“不满足条件就卡死在原地”。下面从物理结构出发,拆解这条链路的核心节点和不可逾越的红线。
一、物理起点:Eden区是唯一默认出生地
所有常规新对象(非大对象、未逃逸)都必须先分配到Eden区。这不是策略,是JVM内存分配的硬性入口规则。Eden占年轻代80%,但它的作用不是“存得多”,而是“快进快出”——这里没有年龄标记、不维护引用关系、不做跨区复制准备,纯粹是对象的第一站。
- 若Eden空间足够:对象落位,流程结束,静待下一次Minor GC
- 若Eden空间不足:立即触发Minor GC,不会尝试往S0/S1里“挤”
- 没有配置-XX:PretenureSizeThreshold时,哪怕对象大到占满Eden,也不会跳过Eden直接进老年代
二、第一道晋升关卡:Survivor区是年龄计数器+缓冲阀
Survivor区(S0/S1)本身不存储新生对象,只承接Minor GC后存活下来的对象。它的物理存在意义只有一个:给对象打年龄标签,并拦截“不够老”的对象进入老年代。
- 每次Minor GC,Eden + 当前From区的存活对象被复制到To区;原From和Eden被清空
- 每成功经历一次Minor GC,对象年龄+1;年龄值记录在对象头中,不依赖所在Survivor区编号
- S0和S1大小严格相等(默认各占年轻代10%),这是复制算法的物理前提——没这个对称性,复制就无法无碎片完成
三、晋升到老年代的三条硬性红线
对象不会“自然长大”就进老年代,必须踩中以下任一条件,且由下一次Minor GC执行搬运:
- 年龄阈值红线:默认15次Minor GC后仍存活(可通过-XX:MaxTenuringThreshold调整),下次GC时直接移入老年代
- 动态年龄红线:某次Minor GC后,To区已存对象按年龄累加,当累计容量 ≥ To区总空间50%,则所有≥该年龄的对象全部晋升(例如:年龄2的对象占To区52%,则所有年龄≥2的对象全部进老年代)
- 空间担保失败红线:Minor GC前检查老年代剩余空间
四、绕过新生代的特例:大对象直通老年代
大对象(如超长byte[]、大ArrayList)不走Eden→Survivor→老年代路径,而是一步到位——前提是配置了-XX:PretenureSizeThreshold且对象大小超过该阈值。
- 该阈值单位是字节,且只对Serial和Parallel GC生效;G1中由-XX:G1HeapRegionSize隐式影响,不响应此参数
- 直通老年代≠绝对安全:老年代若碎片化严重,连续空间不足,仍会触发Full GC甚至OOM
- 未设阈值或对象未超阈值,大对象仍强制走Eden,极易引发频繁Minor GC,这是性能隐患高发点










