【面试专栏|JVM虚拟机】从Serial到ZGC,JVM垃圾收集器进化史


🍃 予枫个人主页
📚 个人专栏 : 《Java 从入门到起飞》《读研码农的干货日常》《Java 面试刷题指南

💻 Debug 这个世界,Return 更好的自己!


引言

垃圾收集器(GC)是JVM的核心组件之一,直接决定了Java程序的性能、吞吐量和延迟。从最基础的Serial收集器,到高性能的ZGC,不同收集器的设计理念和适用场景天差地别。本文将全面对比Serial、ParNew、CMS、G1、ZGC 5大经典垃圾收集器,拆解核心特点、工作原理、优缺点及适用场景,补充面试高频追问,帮你吃透GC选型与优化关键,收藏备用!

文章目录

一、GC收集器核心前提(必懂基础)

在对比5大收集器之前,先明确2个核心前提,避免理解偏差:

  1. 所有GC收集器的核心目标一致:回收堆内存中"无用对象",释放内存空间,避免内存泄漏和OOM;
  2. 收集器的性能衡量指标:吞吐量(CPU用于业务代码的时间占比)、延迟(GC停顿时间)、内存占用、并发能力,不同收集器侧重不同,无绝对"最优",只有"最适配"。

提示:点赞收藏本文,后续面试、调优时直接查阅,省去反复查资料的时间~

二、5大经典垃圾收集器逐一解析(核心章节)

1. Serial 收集器(串行GC)------ 最简单的GC收集器

Serial收集器是最基础、最古老的垃圾收集器,采用"串行回收"机制,即单线程执行垃圾收集,收集期间会暂停所有用户线程(STW,Stop The World)。

核心特点

  • 回收线程:单线程(唯一工作线程执行GC,无线程切换开销);
  • 回收算法:新生代采用"复制算法",老年代采用"标记-整理算法";
  • STW特性:收集期间全程STW,停顿时间与堆内存大小正相关(堆越大,停顿越久);
  • 内存占用:极低(无额外线程开销,实现简单)。

优缺点

✅ 优点:实现简单、内存占用小、单线程无切换开销,在小堆内存(几十MB~几百MB)场景下,停顿时间可接受;

❌ 缺点:STW时间长,无法应对大堆内存(GB级),不适合高并发、低延迟场景。

适用场景

  • 小型应用、嵌入式设备(堆内存较小);
  • 开发、测试环境(追求简单、无额外配置)。

核心参数(JVM配置)

java 复制代码
// 新生代使用Serial收集器
-XX:+UseSerialGC

2. ParNew 收集器(并行新生代GC)------ Serial的并行升级版

ParNew是Serial收集器的"并行版本",核心改进是将新生代的单线程回收改为多线程回收,本质上是"并行收集+STW"的组合,老年代仍依赖Serial收集器。

核心特点

  • 回收线程:多线程(默认线程数等于CPU核心数,可通过参数调整);
  • 回收算法:新生代复制算法,老年代标记-整理算法(复用Serial老年代逻辑);
  • STW特性:收集期间仍会STW,但多线程并行回收,停顿时间比Serial短(堆越大,优势越明显);
  • 兼容性:唯一能与CMS收集器配合使用的新生代收集器。

优缺点

✅ 优点:并行回收,STW时间比Serial短,适配中大型堆内存,兼容CMS;

❌ 缺点:仍有明显STW,多线程存在线程切换开销,老年代回收性能一般。

适用场景

  • 中大型应用(堆内存1~10GB);
  • 追求吞吐量,对延迟有一定要求,但不极致(配合CMS使用)。

核心参数(JVM配置)

java 复制代码
// 新生代使用ParNew收集器
-XX:+UseParNewGC
// 设置GC线程数(默认等于CPU核心数)
-XX:ParallelGCThreads=4

3. CMS 收集器(并发标记清除GC)------ 低延迟优先

CMS(Concurrent Mark Sweep)是第一款追求"低延迟"的垃圾收集器,核心设计是"并发收集",尽量减少STW时间,适合对延迟敏感的场景(如Web应用)。

核心特点

  • 回收线程:多线程并发回收(与用户线程并行执行);
  • 回收算法:老年代采用"标记-清除算法",新生代仍依赖ParNew(或Serial);
  • 核心流程(4步):初始标记(STW,快速标记根对象)→ 并发标记(与用户线程并行,标记所有可达对象)→ 重新标记(STW,修正并发标记的遗漏)→ 并发清除(与用户线程并行,清除无用对象);
  • STW特性:仅在初始标记和重新标记阶段STW,停顿时间极短(毫秒级)。

优缺点

✅ 优点:并发收集,STW时间短,延迟低,适合高并发、低延迟场景(如Web、接口服务);

❌ 缺点:1. 标记-清除算法会产生内存碎片,可能导致大对象无法分配内存,触发Full GC;2. 并发收集占用CPU资源,会降低吞吐量;3. 无法处理"浮动垃圾"(并发清除阶段产生的新垃圾)。

适用场景

  • 高并发Web应用、接口服务(对延迟敏感,允许轻微吞吐量下降);
  • 堆内存较大(10~20GB),且用户线程对延迟要求高。

核心参数(JVM配置)

java 复制代码
// 老年代使用CMS收集器(新生代默认ParNew)
-XX:+UseConcMarkSweepGC
// 开启CMS并发标记阶段的中断机制(减少CPU占用)
-XX:+CMSParallelRemarkEnabled
// 设置CMS触发GC的阈值(默认92%,老年代使用率达到该值触发GC)
-XX:CMSInitiatingOccupancyFraction=80

4. G1 收集器(区域化分代式GC)------ 平衡吞吐量与延迟

G1(Garbage-First)是JDK1.7引入的收集器,设计目标是"平衡吞吐量和延迟",兼顾两者优势,替代CMS成为中大型应用的首选。

核心特点

  • 内存布局:打破"新生代+老年代"的固定分区,将堆内存划分为多个大小相等的独立区域(Region),每个Region可动态切换为新生代或老年代;
  • 回收算法:结合"复制算法"和"标记-整理算法",优先回收垃圾最多的Region(Garbage-First);
  • STW特性:支持"可预测的停顿时间"(通过参数设置最大STW时间),避免长时间停顿;
  • 并发能力:部分阶段与用户线程并行,兼顾吞吐量和延迟。

优缺点

✅ 优点:1. 平衡吞吐量和延迟,可预测停顿时间;2. 无内存碎片(标记-整理算法);3. 适配大堆内存(10GB~100GB);4. 支持动态调整Region角色,灵活应对不同内存场景;

❌ 缺点:1. 内存占用比CMS高(需要额外内存维护Region信息);2. 小堆内存场景下,性能不如Serial/ParNew;3. 并发收集阶段仍会占用一定CPU资源。

适用场景

  • 中大型应用(堆内存10GB~100GB);
  • 既追求吞吐量,又要求低延迟(如电商、金融服务);
  • 替代CMS,解决CMS内存碎片问题。

核心参数(JVM配置)

java 复制代码
// 使用G1收集器
-XX:+UseG1GC
// 设置最大STW停顿时间(毫秒)
-XX:MaxGCPauseMillis=200
// 设置Region大小(默认根据堆内存自动计算,可手动指定)
-XX:G1HeapRegionSize=16m

5. ZGC 收集器(低延迟高并发GC)------ 极致延迟优化

ZGC是JDK11引入的新一代垃圾收集器,核心目标是"极致低延迟",支持TB级堆内存,STW时间控制在10毫秒以内,适合超大型、高并发应用。

核心特点

  • 内存布局:采用"区域化"布局,分为小、中、大三类Region,适配不同大小的对象;
  • 回收算法:基于"标记-整理算法",无内存碎片;
  • 核心技术:采用"着色指针"和"读屏障"技术,实现并发标记、并发整理,几乎全程与用户线程并行;
  • STW特性:仅在初始标记和最终标记阶段有极短STW(通常小于1毫秒),不受堆内存大小影响(即使TB级堆,STW也能控制在10毫秒内)。

优缺点

✅ 优点:1. 极致低延迟,STW时间极短;2. 支持TB级堆内存,适配超大型应用;3. 无内存碎片,无需担心大对象分配问题;4. 并发收集,吞吐量影响小;

❌ 缺点:1. JDK版本要求高(需JDK11及以上);2. 内存占用较高(需要额外内存维护着色指针等信息);3. 目前在国内生产环境的应用不如G1广泛(生态相对较新)。

适用场景

  • 超大型应用(堆内存100GB~TB级);
  • 对延迟要求极高的场景(如高频交易、实时数据分析);
  • JDK11及以上版本,追求极致性能。

核心参数(JVM配置)

java 复制代码
// 使用ZGC收集器
-XX:+UseZGC
// 设置堆内存大小
-Xmx100g
// 设置ZGC的并发线程数
-XX:ZGCThreads=8

三、5大垃圾收集器核心对比表(一目了然)

收集器 回收方式 核心算法 STW特性 内存占用 适用堆大小 核心优势 核心劣势
Serial 串行(单线程) 新生代复制,老年代标记-整理 全程STW,时间长 极低 几十MB~几百MB 简单、无线程开销 停顿久,不适合大堆
ParNew 并行(多线程) 新生代复制,老年代标记-整理 全程STW,时间较短 较低 1~10GB 停顿比Serial短,兼容CMS 仍有STW,线程切换开销
CMS 并发(多线程) 老年代标记-清除,新生代复制 仅初始/重新标记STW,时间极短 中等 10~20GB 低延迟,适配高并发 内存碎片,占用CPU,有浮动垃圾
G1 并发+并行 复制+标记-整理 可预测停顿,时间可控 较高 10GB~100GB 平衡吞吐量与延迟,无内存碎片 小堆性能差,内存占用高
ZGC 并发(多线程) 标记-整理 极短STW(<10ms),不受堆大小影响 100GB~TB级 极致低延迟,支持超大型堆 JDK版本要求高,生态较新

四、面试官追问环节(实战必备)

这部分是面试高频考点,比纯八股文更实用,帮你提前准备应答思路:

  1. 追问1:CMS收集器的"浮动垃圾"是什么?如何解决?

    答:浮动垃圾是CMS并发清除阶段,用户线程产生的新垃圾,这些垃圾无法被当前GC回收,只能等到下一次GC。解决方式:降低CMS触发阈值(如设置-XX:CMSInitiatingOccupancyFraction=80),提前触发GC,预留足够内存容纳浮动垃圾;或升级为G1/ZGC收集器。

  2. 追问2:G1收集器的"可预测停顿时间"是如何实现的?

    答:G1通过"Region分区"和"优先级回收"实现:首先将堆划分为多个小Region,每次GC只回收部分垃圾最多的Region,而非整个堆;其次,通过参数-XX:MaxGCPauseMillis设置最大停顿时间,G1会根据历史回收数据,动态调整本次回收的Region数量,确保停顿时间不超过设定值。

  3. 追问3:ZGC的"着色指针"技术核心作用是什么?

    答:着色指针是ZGC的核心技术,本质是在指针中嵌入"标记位",用于标记对象的回收状态(如可达、不可达)。无需像传统GC那样扫描整个堆标记对象,而是通过指针的标记位直接判断对象状态,实现并发标记和整理,大幅减少STW时间。

  4. 追问4:生产环境中,如何选择合适的垃圾收集器?

    答:核心看3个维度:堆内存大小、延迟要求、吞吐量要求。① 小堆(<1GB):选Serial;② 中堆(1~10GB):追求吞吐量选ParNew,追求延迟选CMS;③ 中大型堆(10~100GB):选G1(平衡吞吐和延迟);④ 超大型堆(>100GB)、极致低延迟:选ZGC(JDK11+)。

五、总结

本文全面解析了Serial、ParNew、CMS、G1、ZGC 5大经典垃圾收集器的核心特点、工作原理、优缺点及适用场景,通过对比表快速区分差异,补充面试高频追问,帮你吃透GC选型与优化关键。

核心结论:无最优收集器,只有最适配的收集器------小型应用选Serial,中大型应用优先G1,高并发低延迟选CMS/ZGC,超大型堆选ZGC。

最后,觉得本文对你有帮助的话,点赞+收藏+关注,后续持续更新JVM核心知识点和面试干货~

相关推荐
逝水如流年轻往返染尘2 小时前
java中类和对象
java
姓蔡小朋友2 小时前
JVM监控
jvm
*.✧屠苏隐遥(ノ◕ヮ◕)ノ*.✧2 小时前
Java 集合 (Collection)
java·开发语言
后端AI实验室2 小时前
我让AI review了自己写的代码,然后删掉了30%
java·ai
SunnyDays10112 小时前
Java 实战:将 Word 文档高效转换为多页 TIFF 图片(含批量处理)
java·word转tiff
一直都在5722 小时前
Java基础面经(二)
java·开发语言
银发控、2 小时前
record类
java·开发语言
jiayong232 小时前
可视化流程设计器技术对比:钉钉风格 vs BPMN
java·前端·钉钉
左左右右左右摇晃2 小时前
MyBatis & MyBatis-Plus 面试题整理
java·笔记