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 的趋势:

更低停顿、更高吞吐、更适应大堆、更多并发。

相关推荐
wuwu_q1 小时前
通俗易懂 + Android 开发实战的方式,详细讲讲 Kotlin 中的 StateFlow
android·开发语言·kotlin
峰哥的Android进阶之路1 小时前
Kotlin面试题总结
android·开发语言·kotlin
froginwe111 小时前
RSS 语法:全面解析与优化指南
开发语言
hygge9992 小时前
MySQL 全体系深度解析(存储引擎、事务、日志、MVCC、锁、索引、执行计划、复制、调优)
数据库·经验分享·mysql·adb·面试
小飞大王6662 小时前
JavaScript基础知识总结(六)模块化规范
开发语言·javascript·ecmascript
Fantasydg2 小时前
MyBatis学习
java·学习·mybatis
qk学算法2 小时前
Collections工具类
java·开发语言
青云交2 小时前
Java 大视界 -- 基于 Java 的大数据可视化在企业生产运营监控与决策支持中的应用
java·echarts·数据采集·实时监控·大数据可视化·智能决策·企业生产运营
迦蓝叶2 小时前
Apache Jena:利用 SPARQL 查询与推理机深度挖掘知识图谱
java·数据挖掘·apache·知识图谱·查询·知识挖掘·推理机