第62篇:垃圾回收器详解(2026版)
📌系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第61篇:JVM内存区域 |
➡️ 下一篇:第63篇:GC调优实战
🗺️ 本文阅读地图(3 分钟速览)
第61篇搞定了JVM内存布局,本篇深入垃圾回收器(GC)的核心世界。GC是JVM的“清道夫”,选对回收器、调好参数,是Java性能优化的核心技能:
| 模块 | 核心问题 | 一句话回答 |
|---|---|---|
| 三大指标 | GC评判标准是什么? | 吞吐量、延迟(STW)、内存占用——三者不可兼得 |
| 六款回收器 | 都有哪些GC? | Serial → Parallel → CMS → G1 → ZGC/Shenandoah,四代演进 |
| 默认GC | 各JDK版本默认是什么? | JDK 8 = Parallel GC,JDK 9+ = G1 GC |
| G1为什么是主流 | 大堆场景谁最稳? | G1是JDK 9+默认GC,兼顾吞吐与延迟,6GB~64GB堆的黄金选择 |
| ZGC/Shenandoah | 极致低延迟用什么? | ZGC和Shenandoah,亚毫秒级停顿,JDK 21+分代优化成熟 |
| CMS去哪了 | 还在用CMS吗? | JDK 14已彻底移除,存量JDK 8可迁移至G1 |
| 面试最爱问 | 高频考点有哪些? | 见文末 🎤 小节 |
一、核心知识点
1. GC三大黄金指标
所有垃圾回收器的设计都在三个指标间做权衡:
| 指标 | 含义 | 优先场景 |
|---|---|---|
| 吞吐量(Throughput) | 业务执行时间 / (业务执行时间 + GC总耗时) | 批处理、离线任务、后台计算 |
| 延迟(Latency / STW) | GC暂停业务线程的时间 | 支付、网关、实时服务、Web应用 |
| 内存占用(Footprint) | GC占用的额外内存空间 | 容器化环境、资源受限场景 |
💡核心权衡:三个指标无法同时做到极致——追求低延迟,吞吐量会下降;追求高吞吐,停顿时间会变长。
2. 四代GC演进脉络
| 世代 | 代表回收器 | 诞生背景 | 核心特点 | 现状 |
|---|---|---|---|---|
| 第一代(串行) | Serial | JDK 1.0,Client模式默认 | 单线程STW,简单轻量 | 仅小型应用 |
| 第二代(并行) | Parallel | 多核CPU普及,追求吞吐量 | 多线程STW,吞吐优先 | JDK 8默认 |
| 第三代(并发) | CMS → G1 | 低延迟需求,CMS碎片问题 | 并发回收,G1分区化 | G1是JDK 9+默认 |
| 第四代(低延迟) | ZGC / Shenandoah | 大堆(100GB+)场景停顿过长 | 亚毫秒级停顿,并发全部操作 | JDK 21+分代优化成熟 |
3. 各JDK版本默认GC速查
| JDK版本 | 默认GC | 说明 |
|---|---|---|
| JDK 8 | Parallel GC(Parallel Scavenge + Parallel Old) | Server模式默认 |
| JDK 9 ~ 21+ | G1 GC | JDK 9起成为默认 |
| JDK 21+(可选) | ZGC(分代ZGC) | JDK 21分代ZGC正式稳定,超低延迟首选 |
💡2026年现状:G1仍是大多数项目的默认选择,ZGC/Shenandoah在极致低延迟场景统治。
二、通俗讲解(1分钟开心学)
把GC想象成清理房间
Serial GC:你一个人打扫一整栋楼(单线程),干活时所有人都得停下等(STW)。适合小房子(小堆)。
Parallel GC:叫来一帮人一起打扫(多线程),干活时大家还是得停下,但速度快多了。适合大厂房(大堆)、不赶时间(对延迟不敏感)。
CMS GC:请了保洁团队,大部分时间边干活边打扫(并发),但打扫完地上会留灰(内存碎片)。偶尔保洁团队太忙还会撂挑子(并发模式失败)。
G1 GC:把整栋楼切成无数个小隔间(Region),每次只打扫垃圾最多的几个隔间(Garbage-First)。可以设定“每次最多打扫X分钟”(停顿时间目标),干不完下次再干。
ZGC / Shenandoah:保洁团队一边打扫一边让住户正常生活(完全并发),几乎感觉不到停顿(亚毫秒级)。适合摩天大楼(超大堆、百GB级)。
一句话总结:Serial是“一人包干”,Parallel是“团队突击”,CMS是“边干边扫”,G1是“分区定点清除”,ZGC/Shenandoah是“无感保洁”。
三、各回收器深度解析
3.1 Serial GC:最基础的串行回收器
核心特点:
- 单线程:新生代用Serial(复制算法),老年代用Serial Old(标记-整理算法)
- STW:回收时暂停所有用户线程
- 适合场景:Client模式、小型应用、堆内存<100MB、单核CPU
# 开启Serial GC-XX:+UseSerialGC💡现状:在2026年,Serial GC基本只用于极简嵌入式环境或学习研究。
3.2 Parallel GC:吞吐量优先的并行回收器
核心特点:
- 多线程并行:新生代Parallel Scavenge(复制算法),老年代Parallel Old(标记-整理算法)
- 吞吐量优先:JDK 8默认GC,目标是最大化应用程序运行时间占比
- STW:仍会暂停所有用户线程,但比Serial快
# JDK 8默认,也可显式开启-XX:+UseParallelGC# 设置GC线程数(默认等于CPU核数)-XX:ParallelGCThreads=8# 设置吞吐量目标(默认99%)-XX:GCTimeRatio=99💡适用场景:批处理、大数据计算、离线任务、对延迟不敏感的后台服务。
3.3 CMS GC:并发低延迟的先行者(已淘汰)
核心特点:
- 并发标记-清除:老年代回收,大部分阶段与应用程序并发执行
- 低停顿:目标是缩短STW时间
- 不压缩:标记-清除算法产生内存碎片
CMS的致命缺陷:
- 内存碎片:长时间运行后碎片严重,可能导致Full GC
- CPU敏感:并发阶段占用CPU资源
- 并发模式失败:老年代空间不足时降级为Serial Old
- 浮动垃圾:并发清理时新产生的垃圾需下次处理
# JDK 8中开启CMS(已过时)-XX:+UseConcMarkSweepGC⚠️重要提醒:CMS在JDK 9被标记为废弃,JDK 14已彻底移除。JDK 8存量应用建议迁移至G1。
3.4 G1 GC:JDK 9+默认的全能型回收器
设计目标:面向大堆内存(6GB~64GB),实现可预测的低停顿时间。
核心机制:
| 机制 | 说明 |
|---|---|
| Region分区 | 将堆划分为多个大小相等的Region(默认2048个),每个Region可扮演Eden、Survivor、Old或Humongous角色 |
| Garbage-First策略 | 优先回收垃圾最多的Region,用最少时间释放最多空间 |
| 停顿预测模型 | 基于历史数据预测每次GC耗时,确保不超过用户设定的停顿时间目标 |
| 混合GC | 同时回收年轻代和部分老年代Region |
# 开启G1(JDK 9+默认)-XX:+UseG1GC# 设置最大停顿时间目标(默认200ms)-XX:MaxGCPauseMillis=100# 设置Region大小(2的幂,1-32MB)-XX:G1HeapRegionSize=16m# 设置堆大小-Xmx16g💡适用场景:绝大多数Web应用、微服务、电商中台,JDK 9+项目首选。
四、实操代码案例 + 场景说明
4.1 查看当前GC配置
# 查看JVM默认GCjava-XX:+PrintCommandLineFlags-version# 输出示例(JDK 8):-XX:+UseParallelGC# 输出示例(JDK 11+):-XX:+UseG1GC# 查看正在运行的应用的GCjstat-gc<pid>1000# 输出各区域GC次数和耗时4.2 GC日志分析与参数配置
# 生产级GC日志配置(推荐)-XX:+PrintGCDetails-XX:+PrintGCDateStamps-XX:+PrintGCTimeStamps-Xloggc:/var/log/app-gc.log-XX:+UseGCLogFileRotation-XX:NumberOfGCLogFiles=10-XX:GCLogFileSize=100MGC日志解读示例:
2026-07-22T10:00:01.123+0800: 5.678: [GC pause (G1 Evacuation Pause) (young), 0.0152345 secs] [Eden: 512.0M(512.0M)->0.0B(512.0M) Survivors: 64.0M->64.0M Heap: 1.2G(4.0G)->700.0M(4.0G)]GC pause:STW暂停0.0152345 secs:暂停时间15msEden: 512M→0B:Eden区清空Heap: 1.2G→700M:堆内存回收约500MB
4.3 生产环境G1推荐配置模板
# 通用G1配置(4GB堆,目标停顿100ms)-Xms4g-Xmx4g-XX:+UseG1GC-XX:MaxGCPauseMillis=100-XX:G1HeapRegionSize=8m-XX:+PrintGCDetails-Xloggc:/var/log/gc.log-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/var/log/heap.hprof4.4 GC调优决策树(2026版)
应用是否需要 < 10ms 的 GC 停顿? ├─ 是 → 堆 > 16GB?→ 是 → 考虑 ZGC(JDK 21+ 分代) │ → 否 → 考虑 G1(调低 MaxGCPauseMillis) └─ 否 → 堆 > 4GB?→ 是 → G1(默认配置即可) → 否 → Parallel GC(追求吞吐量)五、避坑要点
| 错误/误区 | 后果 | 正确做法 |
|---|---|---|
| 盲目使用CMS | JDK 9+不支持,JDK 14已移除 | 迁移至G1 |
| 无界设置-Xmx | 堆内存不足导致Full GC频繁 | 根据业务负载合理设置 |
| G1堆太小(<4GB) | G1管理开销反而拖累性能 | 小堆用Parallel GC |
| 忽略GC日志 | 线上GC问题无法定位 | 生产环境必开GC日志 |
| ZGC堆太小 | ZGC优势无法发挥 | ZGC推荐堆≥16GB |
六、面试高频考点
Q1:垃圾回收器有哪几种?各版本JDK默认是什么?
六种主要回收器:Serial、Parallel、CMS、G1、ZGC、Shenandoah。JDK 8默认Parallel GC;JDK 9+默认G1 GC。
Q2:G1为什么是JDK 9+的默认GC?
G1通过Region化管理和优先级回收(Garbage-First),在大堆(6GB~64GB)场景下实现了延迟与吞吐量的有效折中。相比CMS,G1能压缩内存避免碎片、提供可预测的停顿时间。
Q3:ZGC和G1的核心区别?
G1仍有STW停顿(通常<200ms),ZGC将大部分GC操作并发化,停顿时间<1ms。ZGC采用着色指针+读屏障实现并发转移。ZGC适合超大堆(16GB~TB级)和极致低延迟场景。
Q4:CMS为什么被淘汰?
内存碎片、并发模式失败、浮动垃圾三大缺陷。JDK 9废弃、JDK 14彻底移除。
Q5:ZGC的着色指针是什么?
ZGC利用64位指针的高几位存储对象元数据(标记位),无需在对象头中存储标记信息,使标记和转移操作可完全并发进行。
🎤 面试官追问陷阱(加分题)
追问1:“G1的Region大小如何设置?默认多少个?”
👉 默认最多2048个Region,Region大小通过
-XX:G1HeapRegionSize设置(1~32MB)。Region必须是2的幂,堆≤64GB时G1表现最佳。
追问2:“ZGC在JDK 21有什么重要更新?”
👉 JDK 21引入了分代ZGC(Generational ZGC),进一步降低了CPU开销和内存占用。这是ZGC从实验性走向生产级的关键里程碑。
七、练习题
分析题:某JDK 8应用使用CMS,频繁出现Full GC导致服务超时。推荐什么优化方案?为什么?
场景题:一个金融交易系统,堆内存32GB,要求GC停顿<10ms。推荐什么GC?开启什么参数?
代码题:配置生产环境G1 GC日志,要求输出到
/var/log/app-gc.log,保留10个文件,每个100MB。
📊 你的学习进度
- 当前:第62篇 / 共108篇 ·进阶篇:JVM调优与故障排查(第61~70篇)
- ✅ 已完成:基础篇44篇 + 第45~62篇
- 📖 正在学:第62篇
- ⏳ 待学习:第63~108篇
👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇
👉 下一篇文章预告
🚀下一篇:《第63篇:GC调优实战》
内容简介:GC日志分析实战、JVM参数调优、年轻代/老年代大小调整、G1/ZGC调参最佳实践、生产环境GC问题排查流程。
👉JVM调优专题持续深入,拿下GC调优实战!
📌《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!