from 和 to 空间必须等大,根本原因是为了确保复制算法在最坏情况下(存活对象接近满堆)也能安全完成全量搬迁、引用更新和角色互换,避免越界、布局错乱与分配失败。

From 和 To 空间必须等大,根本原因只有一个:确保一次 GC 过程中所有存活对象都能被完整、安全地复制过去,不丢失、不溢出。
避免复制时空间不足
复制算法不清理单个对象,而是“全量搬迁”存活对象。如果 To 空间比 From 小,哪怕只小 1 字节,就可能在复制最后一个对象时触发越界——不是内存写错位置,就是 GC 失败崩溃。等大小是硬性兜底,不依赖存活率估算,也不靠运气。
- 新生代中对象死亡率虽高(常超 95%),但 JVM 无法提前知道本次 GC 具体存活多少
- 极端情况下(如突发大量长生命周期对象),存活对象可能接近满堆,To 空间必须能容纳“最坏情况”
保证地址计算与指针更新可靠
复制过程要重写所有引用(比如把指向 From 区 A 对象的指针,改成指向 To 区 A′)。这个重写依赖 forwarding 指针和连续内存布局。若 To 空间更小,对象不得不紧凑排列甚至压缩存放,会破坏原有偏移规律,导致 child 指针遍历出错或 forwarding 地址失效。
- copy() 函数里用 $free 累加分配新地址,前提是 To 区是一整块连续、足量的空白空间
- 对象按复制顺序线性摆放,子对象位置可预测;大小不等 → 布局不可控 → 引用修复失败
支撑角色互换机制
GC 结束后,From 和 To 要直接 swap 地址变量(如 $from_start ↔ $to_start),立刻切换分配角色。如果二者容量不同,swap 后新 From 区可能突然变小,下一轮分配立刻失败。
- swap 不是逻辑切换,而是指针交换,要求两个区域完全对等
- JVM 在启动时就固定划分,运行期不调整;等大是最简、最稳的设计选择
不复杂但容易忽略:等大不是为了“平均使用”,而是为复制动作本身提供确定性保障。哪怕实际只搬了 10% 的对象,To 空间也得准备好 100% 的容量余量。











