垃圾回收

本文最后更新于 3 分钟前,文中所描述的信息可能已发生改变。

垃圾回收策略

GC Strategies

垃圾回收需要辨别对象是否需要进行回收(可达), 通常是通过引用和引用链的方式来判断对象是否可达。

引用计数 (Reference Counting)

引用计数是垃圾收集器中的早期策略。在这种方法中,堆中每个对象实例都有一个引用计数。当一个对象被创建时,就将该对象实例分配给一个变量,该变量计数设置为 1。当任何其它变量被赋值为这个对象的引用时,计数加 1(a = b,则 b 引用的对象实例的计数器+1),但当一个对象实例的某个引用超过了生命周期或者被设置为一个新值时,对象实例的引用计数器减 1。任何引用计数器为 0 的对象实例可以被当作垃圾收集。当一个对象实例被垃圾收集时,它引用的任何对象实例的引用计数器减 1。

优点:引用计数收集器可以很快的执行,交织在程序运行中。对程序需要不被长时间打断的实时环境比较有利。

缺点:无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为 0。

可达性分析 (Reachability Analysis)

从一个节点 GC ROOT 开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点,无用的节点将会被判定为是可回收的对象。

在 Java 语言中,可作为 GC Roots 的对象包括下面几种:

  • 虚拟机栈中引用的对象(栈帧中的本地变量表);
  • 方法区中类静态属性引用的对象;
  • 方法区中常量引用的对象;
  • 本地方法栈中 JNI(Native 方法)引用的对象。

垃圾回收算法

Garbage Collection Algorithms

标记-清除

Mark-Sweep

标记-清除算法分为两个阶段:首先标记所有存活对象,然后清除未标记的对象。优点是实现简单,缺点是会产生大量内存碎片,影响后续分配效率。

复制

Copying

复制算法将内存分为两块,每次只在一块分配对象。当一块用满时,将存活对象复制到另一块,然后清空原区域。优点是没有碎片,分配速度快,缺点是内存利用率较低,适合新生代。

标记-整理

Mark-Compact

标记-整理算法先标记所有存活对象,然后将存活对象向一端移动,最后清理无效对象。这样可以消除碎片,提高内存利用率,但对象移动会带来额外开销,常用于老年代。

分代收集

Generational Collection

分代收集算法根据对象存活时间将堆划分为新生代和老年代。新生代采用复制算法,老年代采用标记-清除或标记-整理算法。这样可以针对不同对象特点优化回收效率,是现代 JVM 的主流方案。

垃圾回收模式

GC Patterns

  • Partial GC: 并不收集整个堆的模式。
    • Young GC: 只收集 Young gen 区域的模式。
    • Old GC: 只收集 Old gen 区域的模式。CMS 中存在这种模式。
    • Mixed GC: 收集整个 Young gen 和部分 Old gen 区域的模式。G1 中存在这种模式。
  • Full GC: 收集整个堆,包括 Young gen、Old gen 和 Perm gen(如果存在)等所有区域的模式。

垃圾回收器

Garbage Collectors

串行收集器

Serial GC

串行收集器(Serial GC)是最简单的垃圾回收器,所有回收过程都由单线程完成。适用于单核或小型应用场景,客户端模式下默认选择。优点是实现简单,缺点是回收期间会长时间暂停应用线程,影响响应速度。

  • JVM 参数:-XX:+UseSerialGC
  • 特点:
    • 单线程执行
    • 适合小型应用
    • 暂停时间较长

并行收集器

Parallel GC

并行收集器(Parallel GC)在新生代和老年代回收时都采用多线程并行处理,提升吞吐量,适合多核服务器和后台计算任务。JDK 8 默认收集器。

  • JVM 参数:-XX:+UseParallelGC
  • 特点:
    • 多线程并行收集
    • 吞吐量优先
    • 适合后台批量任务
    • 停顿时间不可控

并发标记清除收集器

Concurrent Mark-Sweep

并发标记清除收集器(CMS)主要针对老年代,采用多线程并发标记和清除,减少停顿时间,适合对延迟敏感的服务。缺点是会产生内存碎片,回收效率受限于并发标记和清除阶段。

  • JVM 参数:-XX:+UseConcMarkSweepGC
  • 特点:
    • 低延迟
    • 并发收集
    • 会产生碎片
    • 停顿时间短但不完全消除

G1 收集器

Garbage First Collector

G1 收集器是 JDK 9+ 默认收集器,适用于大堆内存场景。将堆划分为多个区域,按优先级回收垃圾,支持预测停顿时间。可通过参数设置最大停顿目标,支持 Young GC、Mixed GC 和 Full GC 三种回收模式。

  • JVM 参数:-XX:+UseG1GC -XX:MaxGCPauseMillis=200
  • 特点:
    • 低延迟(目标<10ms)
    • 大堆内存友好(>4GB)
    • 可预测的停顿时间
    • 分区回收,减少全堆扫描

回收模式

  • Young GC:只回收新生代区域,速度快,频率高。
  • Mixed GC:同时回收新生代和部分老年代区域,提升回收效率。
  • Full GC:回收整个堆,包括新生代和老年代,通常在空间不足或晋升失败时触发。

Z 收集器

Z Garbage Collector

ZGC 是 JDK 11+ 引入的超低延迟垃圾收集器,支持 TB 级堆内存。所有回收阶段几乎都并发执行,单次停顿时间通常低于 1ms,非常适合对响应时间极度敏感的大型应用。

  • JVM 参数:-XX:+UseZGC
  • 特点:
    • 超低延迟(<1ms)
    • 支持 TB 级堆内存
    • 并发收集
    • 几乎不影响应用线程

参考

References

定序模块
电商项目开发问题