JVM GC 垃圾回收体系完整讲解
Java 的垃圾回收体系是 JVM 最核心的机制之一。理解 GC,不只是了解某个收集器的特性,而是要理解“对象如何被判断存活”“不同区域如何回收”“不同收集器之间有什么演进关系”。
下面我从体系化角度讲清楚整个 GC 机制。
1. JVM 如何判断对象是否可回收?
现代 JVM 全部采用“可达性分析”(Reachability Analysis) 。
GC 会从一组称为 GC Roots 的节点开始搜索,只要一个对象能通过链路被 GC Roots 引用到,就被视为存活,否则就是不可达对象,可以回收。
典型 GC Roots 包括:
- 栈帧中的局部变量表
- 方法区中的静态变量
- 常量池中的引用
- JNI 本地引用
- 正在运行的线程自身
- 类加载器等基础结构
这种模型的核心特点是:以图遍历方式判断对象生命周期,避免引用计数的循环引用问题。
2. JVM 中的四种引用类型(为什么要设计成这么多?)
JVM 为了更灵活地管理内存,引入了 4 类引用强度不同的引用模型:
强引用(Strong Reference)
正常使用的引用,只要存在强引用,垃圾回收器永不回收。
软引用(Soft Reference)
内存紧张时才会被回收,常用于缓存。
弱引用(Weak Reference)
下一次垃圾回收必定回收,非常适合 ThreadLocal、WeakHashMap 这种弱生命周期资源。
虚引用(Phantom Reference)
用于追踪对象被回收的时间点,不能通过它获得对象,是最弱的引用。
这套引用体系为 JVM 提供了非常细粒度的生命周期管理能力。
3. 基本的垃圾回收算法
所有现代垃圾收集器的基础都是以下几种经典算法。
标记-清除(Mark-Sweep)
扫描对象并标记存活对象,然后清理未标记对象。
缺点是会形成大量内存碎片。
复制算法(Copying)
把内存分成两块,只使用一块,GC 时将活对象复制到另一块,效率非常高。
新生代大量使用复制算法。
标记-整理(Mark-Compact)
标记后,将存活对象统一移动到内存一端,避免碎片问题。
常用于老年代。
分代收集(Generational Collection)
基于对象生命周期不同,把堆划分为新生代和老年代,各自采用不同算法,是现代 GC 的灵魂设计。
4. 分代收集 vs 分区收集(Region-based)
两者是不同的设计哲学:
分代收集
按对象生命周期划分区域:
- 新生代:对象短命,采用复制算法
- 老年代:对象更稳定,采用标记整理
这是 JVM 经典堆结构。
分区收集(Region-based)
代表:G1、ZGC、Shenandoah
把整个堆划分成等大小的 Region,不再固定新老年代布局,而是动态分配不同 Region 的角色。
优势是对大堆更友好,也让 GC 调度更灵活。
5. JVM 的内存分配策略
对象的生命周期大致如下:
(1)对象通常先分配在 Eden
(2)Eden 满时触发 Minor GC,存活对象复制到 Survivor
(3)多次 Minor GC 后晋升到老年代
(4)大对象可能直接进入老年代
(5)栈上分配与标量替换可能让对象不进入堆
(6)Survivor 不够时依赖老年代“担保机制”
分代模型的目标是让 GC 把主要压力放在新生代,因为大量对象会快速死亡,复制代价最低。
6. 什么时候会触发 Full GC?
常见触发条件包括:
- 老年代空间不足
- Metaspace 空间不足
- 新生代 GC 后晋升失败
- System.gc() 被调用(可能触发)
- CMS 的 concurrent mode failure 失败导致 Full GC
- G1 回收失败时也可能触发 Full GC
Full GC 是 GC 中代价最高的,需要尽量避免。
7. HotSpot 中的主要垃圾收集器
按历史演进来看,可以分为几个阶段:
早期收集器
- Serial
- ParNew
- Parallel Scavenge / Parallel Old
适用中小堆,停顿明显。
CMS(Concurrent Mark Sweep)
第一个低停顿老年代收集器,采用多线程并发标记与清除,减少停顿时间。
优点:
- 停顿时间短
- 适合对响应要求非常高的服务端系统
缺点:
- 会产生碎片
- 同时并发占用 CPU
- concurrent mode failure 会触发 Full GC
- 已经过时,被 G1 取代
G1(Garbage First)
JDK 9 及之后的默认收集器,关键特性:
- 堆被划分成 Region
- 使用分区思想,不再固定新老年代
- 通过计算各 Region 的垃圾含量,优先回收收益最高的
- 回收时会整理内存,避免碎片
- 提供可预测的停顿时间目标
G1 适合大堆、服务端、延迟要求较高的系统。
ZGC(Z Garbage Collector)
ZGC 是新一代超低延迟垃圾收集器,特点:
- 停顿时间通常 < 10ms
- 支持数百 GB 到 TB 级堆
- 所有 GC 阶段几乎都并发执行
- 采用着色指针(Colored Pointers)
- 通过读屏障(Load Barrier)实现并发移动对象
ZGC 基本上解决了 JVM 在大内存时代的痛点。
8. 整体总结
我对 JVM GC 体系的理解是,它不是某个算法或收集器,而是一整套从“判断对象存活 → 回收策略 → 内存分代 → 收集器演化”的完整系统。
可达性分析保证了准确性;
四种引用提供了灵活性;
复制、标记整理等算法提供了基础;
分代收集保证了整体效率;
而 G1、ZGC 代表了现代 JVM GC 的趋势:
更低停顿、更高吞吐、更适应大堆、更多并发。
