JVM 垃圾回收(GC)

一、第一性原理层(Why)

1. 为什么需要垃圾回收

根本问题

程序如何判断一块内存是否还“有价值”?

在现代高级语言中:

如果完全依赖人工释放:

结论

垃圾回收的本质,是把“内存生命周期管理”从业务逻辑中剥离,交由运行时系统统一治理。


2. GC 的本质定义

无论实现如何变化,所有 GC 都在解决同一个问题:

在不破坏程序语义的前提下,找出仍然可能被使用的对象,其余内存可以被安全重用。

抽象为两个不可分割的子问题:

  1. **存活对象发现(Live Object Discovery)**
  2. **内存空间重用(Space Reclamation & Reuse)**

二、理论模型层(What)

3. 对象“是否存活”的理论判定

3.1 引用计数模型(被否定的方案)

思想

被否定的根本原因

JVM 放弃该方案,并非性能问题,而是正确性难以保证


3.2 可达性分析模型(GC 的理论基石)

核心思想

对象是否存活,不取决于“被引用次数”,而取决于是否仍可被程序访问

模型定义:

这是 JVM GC 的第一性理论基础。


4. GC Roots 的哲学含义

GC Roots 不是随意选择,而是满足一个原则:

只要程序还能“直接使用”的对象,就必须作为根。

因此包括:


5. 引用强度模型(对象生存策略)

引用不是二元的(有 / 无),而是一个策略梯度

引用类型本质定位设计目的
强引用必须存活程序正确性
软引用可牺牲内存弹性(缓存)
弱引用不阻止回收生命周期绑定
虚引用仅做通知资源回收协调

引用模型的本质,是让程序参与“内存价值排序”


三、分代与对象行为假说(Why + What)

6. 分代收集的理论前提

JVM 并非随意分代,而是基于三条经验假说:

  1. **弱分代假说**:绝大多数对象朝生夕灭
  2. **强分代假说**:活得越久的对象越难死亡
  3. **跨代引用假说**:跨代引用远少于同代引用

GC 分代不是优化技巧,而是对象行为统计学


7. 分代的抽象角色划分

本质角色回收目标
新生代高死亡率区快速回收
老年代高稳定区减少频率

分代的真正目的:

用不同策略处理不同“生存概率”的对象。


四、核心回收算法(How)

8. 三大基础算法的哲学权衡

8.1 标记-清除(Mark-Sweep)

适用场景:


8.2 标记-复制(Mark-Copy)

本质适配:

高死亡率区域(新生代)


8.3 标记-整理(Mark-Compact)

哲学权衡:

停顿时间 vs 吞吐量


五、并发 GC 的不变量与工程约束

9. 为什么并发 GC 如此困难

根本冲突:

GC 在“看对象图”,而程序在“改对象图”。


10. 三色标记不变量

颜色含义
未访问(可能垃圾)
已访问,未扫描完
已完全扫描

并发正确性的核心不变量

黑对象不能直接引用白对象


11. 两大并发修正思想

思想代表本质
增量更新CMS关注“新增引用”
原始快照(SATB)G1 / ZGC固定起始视图

六、HotSpot 架构支撑机制(How)

12. Safepoint / Safe Region

GC 不是随时可做的,而必须在引用关系稳定点执行。

Safepoint 的本质:


13. OopMap

OopMap 解决的问题不是“快”,而是:

如何在暂停时准确知道哪里是引用。


14. 记忆集与卡表

设计目标:

避免全堆扫描老年代。

卡表是:


七、垃圾收集器 = 策略组合体

15. 衡量 GC 的三大指标

指标含义
吞吐量程序执行效率
延迟停顿时间
内存占用运行成本

GC 设计是典型的不可能三角问题


16. 典型收集器的设计定位

收集器核心追求代价
Serial极简长停顿
Parallel吞吐延迟不可控
CMS低延迟碎片
G1可预测实现复杂
ZGC极低延迟架构复杂

八、现代 GC 的演进趋势

17. 演进主线

对象规模 ↑ → 堆容量 ↑ → 人类容忍停顿 ↓

因此:

关联内容(自动生成)