复制算法将新生代划分为eden区和两个survivor区(s0、s1),新对象分配在eden区,minor gc时将eden和from区存活对象复制到to区并清空源区,通过角色互换避免碎片;因新生代对象98%朝生夕死,复制少量存活对象效率高,但需空间换时间,内存利用率约90%,存活对象达年龄阈值15即晋升老年代。

Java 中的复制算法是一种专为新生代设计的高效垃圾回收策略,核心思路是“用空间换时间”,通过内存分区和对象迁移来避免碎片、提升回收速度。
复制算法怎么分内存
它把新生代内存划成三块:一块 Eden 区 + 两块大小相等的 Survivor 区(通常叫 S0 和 S1)。新对象一律分配在 Eden 区;当 Eden 满了,就触发一次 Minor GC,只处理新生代。
- GC 开始时,从 GC Roots 出发,标记所有存活对象
- 把 Eden 和其中一个 Survivor(比如 S0)中所有存活对象,统一复制到另一个空的 Survivor(S1)
- 复制过程中,对象按顺序紧密排列,天然消除内存碎片
- 复制完成后,Eden 和 S0 被一次性清空,S1 成为新的存活区,S0 变为空闲区,下次 GC 时角色互换
为什么新生代适合用复制算法
因为绝大多数新创建的对象生命周期极短——统计表明,98% 以上的对象在第一次 GC 时就已死亡。这意味着每次 Minor GC 只需复制少量存活对象,效率极高。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 不用遍历整个堆,只扫描 Eden + 一个 Survivor,停顿时间短
- 复制后内存连续,后续对象分配只需移动指针,速度快
- 天然规避标记-清除带来的碎片问题,避免大对象分配失败
对象怎么留在新生代或晋升到老年代
复制不是无限循环的。每次成功复制后,对象的“年龄”加 1(记录在对象头中)。达到一定阈值(默认 15 次),就直接晋升到老年代。
- 可通过 -XX:MaxTenuringThreshold 调整晋升年龄
- 大对象(如长数组)可能直接分配到老年代,避免在新生代反复复制
- 如果 Survivor 空间不够容纳所有存活对象,多余部分也会直接进入老年代(称为“担保机制”)
复制算法的代价和限制
它高效但有明确前提:存活对象必须远少于死亡对象。一旦新生代中长期存活对象变多,复制开销就会显著上升。
- 内存利用率只有约 1/2(因为总要预留一块空的 Survivor)
- 不适合老年代——那里对象存活率高,复制成本太大
- 需要额外空间做“担保”,若老年代没足够空间容纳晋升对象,会触发 Full GC
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










