survivor区from和to的交换是复制算法高效运行的关键设计,确保每次minor gc开始时总有一个空的survivor区可用;交换发生在gc结束时,将原to变为新from、原from变为新to,为下一轮gc准备扫描源与写入目标。

Survivor区From和To的交换不是简单的名字轮换,而是复制算法高效运行的关键设计。它确保每次Minor GC开始时,总有一个空的Survivor区可用,避免内存碎片和写入冲突。
为什么必须交换?
复制算法要求“一边读、一边写”,即扫描源区域(Eden + From)中存活对象,统一复制到目标区域(To)。如果To区不为空,就会发生覆盖或校验开销;如果两个Survivor都参与读写,逻辑会混乱且无法保证原子性。交换的本质是角色重置:把刚完成写入的To变成下一轮的From(待扫描),把刚被清空的From变成下一轮的To(待写入)。
交换发生的准确时机
交换发生在Minor GC全过程的末尾,且仅在一次GC结束后立即完成:
- GC开始前:Eden + 当前From区有对象,To区为空
- GC执行中:存活对象从Eden和From复制到To(含年龄+1、晋升判断)
- GC结束时:Eden和From被清空,To已填入存活对象
- 紧接着交换:原To成为新From,原From成为新To
交换背后的资源约束
HotSpot虚拟机始终只使用一个Survivor区作为“接收端”,另一个作为“源端”或闲置区。这种单向写入依赖交换来维持状态对称:
- 两个Survivor大小严格相等(默认各占新生代1/10),无法动态伸缩
- 没有“第三个缓冲区”,所以必须靠交换复用空间
- 若某次GC后To区溢出(比如大对象涌入或Survivor过小),多余对象直接晋升老年代,不等待交换
交换与对象年龄的关系
交换本身不改变对象年龄,但为年龄累加提供上下文:
- 每次对象从From复制到To,年龄才+1
- 交换后,这批对象在下一轮GC中就处于新的From区,等待再次被扫描
- 年龄阈值(默认15)是在From→To复制过程中判定的,不是在交换那一刻判定
这套机制看起来绕,实则是用确定性的空间复用,换取低延迟、无碎片的年轻代回收。只要理解“空To是前提,复制是动作,交换是收尾”,就能看清整个流程的闭环逻辑。











