serial与serial old组合构成串行分代回收方案:新生代用serial复制算法(eden/survivor切换),老年代用serial old标记-整理算法;全程单线程执行,stw不可避免,适合小堆或嵌入式场景。

Serial 收集器本身只负责新生代,它不处理老年代;真正与它配合完成“分代收集”的是 Serial Old 收集器。两者组合(-XX:+UseSerialGC)构成一套完整的串行分代回收方案:新生代用复制算法,老年代用标记-整理算法。
新生代:Serial 用复制算法,靠 Eden/Survivor 切换
Serial 在新生代中将内存划分为 Eden、From Survivor(S0)、To Survivor(S1)三块区域。每次 Minor GC 时:
- 只扫描 Eden 区和当前 From 区中的存活对象;
- 将它们复制到空的 To 区,过程中按年龄判断是否晋升——达 -XX:MaxTenuringThreshold(默认 15)或 To 区放不下,就直接进老年代;
- 复制完成后,Eden 和 From 区被清空,然后 S0 与 S1 角色互换,为下一次 GC 准备好新的 “To” 目标区。
这种机制天然避免碎片,也契合新生代对象“朝生暮死”的特点——复制成本低,效率高。
老年代:Serial Old 用标记-整理,端对齐压缩内存
当对象晋升到老年代,或触发 Full GC 时,Serial Old 接管回收工作,执行三步操作:
- 从 GC Roots 开始标记所有可达对象;
- 把所有被标记的存活对象向堆起始端(如低地址)连续移动,挤掉中间空隙;
- 更新所有指向这些对象的引用,并清理边界外的剩余空间。
相比标记-清除,标记-整理不产生碎片,适合老年代对象存活率高、不宜频繁复制的场景。
串行 ≠ 慢,但 STW 不可避免
整个流程由单一线程独占执行,用户线程全程暂停(Stop-The-World)。这带来两个实际效果:
- 没有线程创建、同步、通信开销,在几十 MB 小堆、单核或嵌入式环境里,回收反而更稳更快;
- 一旦堆变大或对象变多,STW 时间会明显拉长,比如几百 MB 老年代整理可能停顿数百毫秒,服务端应用通常无法接受。
它不是过时的设计,而是特定场景下的合理选择——简单、可控、资源消耗最低。











