java新生代垃圾回收默认自动采用复制算法,通过eden区与两个survivor区(s0/s1)按8:1:1比例协作实现:minor gc时将存活对象复制到空闲survivor区或晋升老年代,清空eden和原survivor区,天然避免碎片并支持指针碰撞分配。

Java 中复制算法在新生代垃圾回收里不是“手动启用”的功能,而是 JVM 默认且自动采用的核心机制。它不靠代码调用,而是由 HotSpot 虚拟机在运行时依据分代设计天然驱动——只要对象分配在新生代,GC 触发时就会按复制逻辑工作。
新生代结构直接体现复制算法的设计
HotSpot 新生代被划分为三个子区域:Eden 区 + 两个 Survivor 区(S0 和 S1),默认比例是 8:1:1。这个划分不是随意的,而是为复制算法服务的:
- 新对象全部分配在 Eden 区(From 空间的主要部分)
- 每次 Minor GC 时,JVM 从 GC Roots 开始标记存活对象
- 存活对象被统一复制到一个空闲的 Survivor 区(To 空间);如果对象年龄够大或 Survivor 空间不足,则直接晋升到老年代
- Eden 区和另一个 Survivor 区(上一轮的 To)被整体清空
- 两个 Survivor 区角色互换,为下一次 GC 做准备
为什么非得用复制算法?关键在对象生命周期特征
IBM 实际统计表明,98% 的 Java 对象“朝生夕死”。这意味着每次 GC 后,Eden 区几乎全是垃圾,只有极少数对象需要保留。复制算法在这种场景下效率极高:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 不用逐个清理碎片化的死亡对象,只需搬运少量存活对象
- 复制过程天然整理内存——所有存活对象在 To 空间连续排列,彻底避免碎片
- 后续对象分配可使用 bump-the-pointer(指针碰撞)方式,仅移动一个指针即可完成分配,极快
你不需要写代码启用它,但可以影响它的行为
虽然复制逻辑由 JVM 自动执行,但你可以通过参数调整其实际效果:
- -XX:SurvivorRatio=8:控制 Eden 与单个 Survivor 的比例(默认值,即 8:1:1)
- -XX:MaxTenuringThreshold=15:设置对象在 Survivor 区之间最多复制多少次才晋升老年代(实际阈值由 JVM 动态计算,但上限由此控制)
- -Xmn2g:直接指定新生代总大小,间接影响 Eden 和 Survivor 的绝对容量
- 若频繁发生 Survivor 区溢出(to-space overflow),说明存活对象太多或 Survivor 太小,可能触发提前晋升,这时需结合 GC 日志分析并调参
它和“纯两块空间”教科书模型略有不同,但本质未变
严格来说,新生代不是简单的 From/To 二分,而是三区协作。但核心思想完全一致:每次回收都把“当前使用中”的多个区域(Eden + 一个 Survivor)里的存活对象,集中复制到“备用”的一块连续区域(另一个 Survivor 或老年代),然后整块清空。这种设计既保留了复制算法的高效与无碎片优势,又通过 Survivor 区缓冲,给短期存活对象多一次“观察期”,进一步提升筛选精度。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










