8:1:1指Eden与两个Survivor区的默认初始比例,即Eden占年轻代80%、S0和S1各占10%,由-XX:SurvivorRatio=8控制,本质是基于对象朝生夕死特性在吞吐与复制成本间的经验平衡。

Java 垃圾回收中年轻代的 8:1:1 划分,指的不是内存大小的绝对比例,而是 默认的初始分配比例 —— Eden 区占年轻代总空间的 80%,两个 Survivor 区(S0 和 S1)各占 10%。这个比例由 JVM 参数 -XX:SurvivorRatio=8 控制(默认值通常为 8),它表示 Eden : Survivor(单个) = 8 : 1,因此整体为 8 : 1 : 1。
为什么是 8:1:1?核心是权衡吞吐与复制成本
年轻代采用 复制算法(Copying GC),对象先在 Eden 分配;GC 触发时,存活对象被复制到一个空的 Survivor 区(比如 S0);下次 GC 再复制到另一个 Survivor 区(S1),同时清空前一个。这种“来回复制”需要两个 Survivor 区互为备份。
8:1:1 的设计基于经验观察:
• 大多数新创建对象“朝生暮死”,Eden 区承担主要分配压力,需要足够大以减少 GC 频率;
• Survivor 区只需容纳少量“熬过一次 GC”的年轻对象,10% 已能满足大多数应用的幸存率(通常低于 5%);
• 两个 Survivor 区必须等大,否则复制时可能放不下——所以不能一个 1%、一个 9%,必须对称。
这个比例不是固定不变的
JVM 会根据实际 GC 行为动态调整 Survivor 区大小,这个机制叫 Survivor 空间担保(Target Survivor Ratio) 或 自适应大小策略(AdaptiveSizePolicy):
- 如果某次 Minor GC 后,存活对象太多,一个 Survivor 区装不下,JVM 会把部分对象直接晋升到老年代(即使年龄没到阈值);
- 若连续几次 GC 后,实际存活对象始终远小于当前 Survivor 容量,JVM 可能自动调小 Survivor 区、扩大 Eden(仍保持 S0=S1);
- 可通过
-XX:-UseAdaptiveSizePolicy关闭该行为,此时比例严格按-XX:SurvivorRatio固定。
怎么看自己程序的实际划分?
启动时加参数 -XX:+PrintGCDetails -Xloggc:gc.log,观察日志中的年轻代布局。例如:
立即学习“Java免费学习笔记(深入)”;
[GC (Allocation Failure) [PSYoungGen: 69952K->4288K(76672K)] ...这里 PSYoungGen: A->B(C) 中的 C 是年轻代总容量(Eden + S0 + S1),A 是 GC 前已用,B 是 GC 后剩余。再结合 -XX:+PrintGCTimeStamps 和工具如 jstat -gc <pid>,可算出 Eden/Survivor 实际大小。
调优建议:别盲目改 8:1:1
除非明确观察到问题,否则不建议手动修改 SurvivorRatio:
- Survivor 区太小 → 频繁提前晋升,老年代压力大,可能引发 Full GC;
- Survivor 区太大 → Eden 变小,Minor GC 更频繁,吞吐下降;
- 更有效的调优方向通常是:调整年轻代总大小(
-Xmn)、控制对象生命周期(避免短命对象持有长命引用)、或优化对象分配模式(如使用对象池需谨慎)。
本质上,8:1:1 是 HotSpot 在通用场景下的经验平衡点——够大以降低 Minor GC 次数,够小以节省空间,且为复制算法留出必要冗余。理解它背后的取舍,比记住数字更重要。


















