Serial 垃圾收集器单线程工作原理

作者:袖梨 2026-07-09
Serial垃圾收集器是JVM中最基础的单线程STW收集器,新生代用复制算法(Eden/Survivor切换),老年代由Serial Old用标记-整理算法处理,全程单线程独占、所有用户线程暂停,适合小堆或嵌入式场景。

Serial 垃圾收集器的单线程工作原理,核心在于“一个线程、全程独占、全局暂停”。它不是简单地“用一个线程干活”,而是整个 GC 过程由唯一一条 JVM 级 GC 线程串行执行,期间所有用户线程(即你的业务代码线程)必须停止运行——这就是 Stop-The-World(STW)。

新生代:靠复制算法完成快速清理

Serial 收集器在年轻代使用复制算法,依赖 Eden 区和两个 Survivor 区(S0/S1)协作:

  • 每次 Minor GC 触发时,只扫描 Eden 区 + 当前 From Survivor 区中的存活对象;
  • 将这些存活对象一次性复制到空闲的 To Survivor 区(若对象年龄达标或 To 区空间不足,则直接晋升老年代);
  • 复制完成后,清空 Eden 和 From 区,再交换 S0/S1 的角色,为下次 GC 准备好新的 From/To;
  • 整个过程不整理碎片、不遍历死亡对象,只搬运存活者,因此速度快、内存连续。

老年代:靠标记-整理算法维持空间规整

当搭配 Serial Old 收集器处理老年代时,采用三阶段标记-整理(Mark-Compact):

  • 标记:从 GC Roots 开始,递归标记所有可达对象;
  • 整理:把所有被标记的存活对象向内存一端(如起始地址)紧凑移动,消除中间空隙;
  • 更新与清理:修正所有指向这些对象的引用地址,并回收整理后边界外的剩余空间。

这种方式避免了内存碎片,也比复制算法更省空间——因为老年代对象存活率高,复制成本太大。

单线程 ≠ 效率低,但停顿不可绕过

它的“单线程”优势恰恰来自无并发开销:

  • 没有线程创建、同步锁、任务分派、缓存一致性等额外消耗;
  • 在几十 MB 小堆、单核 CPU 或嵌入式环境里,实际吞吐和响应反而更稳;
  • 但代价明确:每次 GC 必然 STW,暂停时间随存活对象数量线性增长;
  • 堆越大、对象越多、CPU 核心越多,它越显得“力不从心”,不适合现代服务端应用。

如何确认它正在运行

可通过 JVM 参数和日志验证:

  • 显式启用:-XX:+UseSerialGC(同时激活 Serial + Serial Old);
  • 查看默认配置:java -XX:+PrintCommandLineFlags -version,若未出现 UseSerialGC,说明当前未使用;
  • 开启 GC 日志:-Xlog:gc*,gc+heap=debug,日志中出现 SerialSerialOld 字样即为生效。

相关文章

精彩推荐