面试知识库
极高 进阶

堆内存分代模型#

一句话答案#

堆分新生代(Eden:S0:S1=8:1:1)和老年代,新对象在 Eden 分配,GC 存活后复制到 Survivor,年龄达 15 晋升老年代。

核心要点

新生代: Eden(80%) + S0(10%) + S1(10%)

GC流程: Eden满→Minor GC→存活复制到S1→年龄+1→达阈值(默认15)→晋升老年代

大对象直接进老年代:超过 -XX:PretenureSizeThreshold

面试回答(2分钟版)

堆内存采用分代模型,分为新生代和老年代。新生代内部按 8:1:1 的比例划分为 Eden 区和两个 Survivor 区(S0、S1)。新对象优先在 Eden 分配,Eden 满时触发 Minor GC,存活对象被复制到其中一个 Survivor 区,年龄加 1,每次 Minor GC 两个 Survivor 轮换使用。对象年龄达到阈值(默认 15,CMS 下是 6)就晋升到老年代。之所以用 8:1:1 的比例,是因为新生代对象朝生夕灭,每次 GC 存活率很低,只需要 10% 的 Survivor 空间就够接收存活对象,这样内存利用率达到 90%。超过 -XX:PretenureSizeThreshold 的大对象会跳过新生代直接分配到老年代,避免在 Eden 和 Survivor 之间反复复制。另外还有动态年龄判断机制,如果 Survivor 区中相同年龄的对象总大小超过 Survivor 空间的一半,那么年龄大于等于该年龄的对象可以直接晋升老年代,不必等到默认阈值。

追问与易错

追问方向:

  • “为什么 Eden 和 Survivor 比例是 8:1:1?”→ 新生代对象朝生夕灭,每次 Minor GC 存活率极低(通常 < 10%),只需 10% 的 Survivor 空间就够接收存活对象,这样内存利用率达 90%
  • “大对象直接进老年代的阈值是多少?”→ 通过 -XX:PretenureSizeThreshold 设置(默认 0 即不开启),G1 中超过 Region 大小一半的对象被视为 Humongous 对象直接分配到老年代
  • “对象什么时候晋升老年代?”→ 三种情况:① 年龄达到阈值(默认 15,CMS 下是 6) ② 动态年龄判断:Survivor 中相同年龄对象总大小超过 Survivor 一半则该年龄及以上直接晋升 ③ Survivor 放不下直接晋升

易错点:

  • ❌ 所有对象都从 Eden 分配——大对象直接进老年代
  • ❌ 混淆 Minor GC 和 Full GC 的触发条件