深入解析 JVM 垃圾回收算法:经典 vs 新型 GC 算法

文章目录

  • [一、JVM 常见垃圾回收算法](#一、JVM 常见垃圾回收算法)
    • [1. 标记-清除(Mark-Sweep)](#1. 标记-清除(Mark-Sweep))
    • [2. 标记-整理(Mark-Compact)](#2. 标记-整理(Mark-Compact))
    • [3. 复制算法(Copying)](#3. 复制算法(Copying))
    • [4. 分代收集算法(Generational Collection)](#4. 分代收集算法(Generational Collection))
    • [5. 增量收集算法(Incremental Collection)](#5. 增量收集算法(Incremental Collection))
  • [二、新型 GC 算法(G1、ZGC、Shenandoah 等)](#二、新型 GC 算法(G1、ZGC、Shenandoah 等))
    • [1. G1 垃圾回收器(Garbage-First GC)](#1. G1 垃圾回收器(Garbage-First GC))
    • [2. ZGC(Z Garbage Collector)](#2. ZGC(Z Garbage Collector))
    • [3. Shenandoah 垃圾回收器](#3. Shenandoah 垃圾回收器)
  • [三、三色标记法:现代 GC 算法的基础](#三、三色标记法:现代 GC 算法的基础)
  • [四、总结:GC 算法的演进与优化](#四、总结:GC 算法的演进与优化)

垃圾回收(Garbage Collection,GC)是 Java 程序中非常重要的部分,涉及到内存的自动管理。不同的垃圾回收器(GC)使用不同的算法来完成内存回收任务。随着 Java 版本的更新,垃圾回收算法也在不断演进,特别是 JDK 1.8 之后 ,引入了新的 GC 算法,比如 三色标记法ZGC 等。


一、JVM 常见垃圾回收算法

JVM 中的垃圾回收器并非只有一种,而是有多种不同的算法来实现垃圾回收。每种算法有其适用的场景和优缺点。我们将从 经典的垃圾回收算法 入手,逐步解析现代的 新型算法

1. 标记-清除(Mark-Sweep)

流程

  1. 标记阶段:从 GC Roots 开始标记所有存活的对象。
  2. 清除阶段:回收所有未标记的对象(即垃圾对象)。

优点

  • 简单直观。
  • 不需要整理对象内存,适用于大多数简单的垃圾回收需求。

缺点

  • 内存碎片:因为对象没有按顺序清理,可能会产生内存碎片。
  • 不高效:全停顿的标记过程可能会导致长时间的停顿。

2. 标记-整理(Mark-Compact)

在标记-清除的基础上,标记之后会整理存活对象的位置。

流程

  1. 标记阶段:与标记-清除相同,标记存活对象。
  2. 整理阶段:将所有存活对象移动到堆的一端,整理后释放掉无用的空间。

优点

  • 解决内存碎片:整理步骤减少了碎片化,能有效利用内存。
  • 对老年代尤为适用。

缺点

  • 对象的移动会导致额外的开销,需要停止应用线程。
  • 整理过程可能比标记过程还要复杂。

3. 复制算法(Copying)

复制算法将内存分为两块区域,使用一块区域存放活动对象,另一块作为备用。垃圾回收时,将存活的对象从一块区域复制到另一块。

流程

  1. 将堆划分为两个区域:Eden区Survivor区
  2. 新生代(年轻代)使用复制算法,每次进行垃圾回收时,存活的对象被复制到另一块区域。
  3. 剩余的空间被回收。

优点

  • 没有碎片:使用一块区域存储存活对象,直接复制到另一块区域。
  • 适合频繁创建和销毁对象的场景(例如年轻代)。

缺点

  • 需要两倍的内存空间来进行复制。
  • 只适用于年轻代(新生代)。

4. 分代收集算法(Generational Collection)

JVM 中的垃圾回收通常会使用 分代收集算法 ,将内存划分为不同的区域进行回收。分代收集算法的核心思想是:大部分对象都是短命的,只有少部分对象是长期存在的。

流程

  1. 年轻代(Young Generation):对象大多在年轻代中生成和销毁,使用复制算法。
  2. 老年代(Old Generation):长期存活的对象会被移到老年代,使用标记-整理算法。

优点

  • 提升回收效率:年轻代采用复制算法,老年代采用标记-整理或标记-清除算法。
  • 分代算法使得垃圾回收针对不同生命周期的对象有不同的优化策略。

缺点

  • 对老年代的回收仍然有较高的停顿时间。
  • GC 可能会涉及到多个区域的回收。

5. 增量收集算法(Incremental Collection)

增量收集是对标记-清除算法的一种改进,它将标记过程分割成多个小阶段,减少每次标记的停顿时间。

优点

  • 减少停顿时间:通过增量方式逐步进行标记,降低全停顿的时间。

缺点

  • 仍然可能存在标记失败的情况,处理起来较为复杂。

二、新型 GC 算法(G1、ZGC、Shenandoah 等)

1. G1 垃圾回收器(Garbage-First GC)

G1 是为了替代 CMS(并发标记清除)而设计的一种新的垃圾回收器。它将堆划分为多个大小相等的 Region ,每个 Region 可以动态调整为 年轻代老年代Humongous 区域(用于存放大对象)。

特点

  • 低停顿目标:G1 通过分区和增量标记减少了 STW 停顿时间,能够控制每次停顿的最大时长。
  • 并行和并发:G1 支持多线程并行回收,且垃圾回收的各个阶段可以并发执行。

优点

  • 适用于需要低延迟的应用(如 Web 应用、实时系统)。

缺点

  • 对大堆内存的支持不如 CMS,可能在内存很大的系统中表现不如预期。

2. ZGC(Z Garbage Collector)

ZGC 是一个低延迟垃圾回收器,旨在通过 并发标记并发整理 实现最小的停顿时间。它可以在 数百GB 的堆内存中运行,停顿时间几乎可以忽略不计。

特点

  • 几乎零停顿:ZGC 的停顿时间通常在 10 毫秒以内。
  • 并发回收:几乎所有的垃圾回收都在并发线程中完成。

优点

  • 适用于大内存和低延迟的系统。

缺点

  • 内存开销较大,需要更多的资源来管理堆。
  • 目前仅在 JDK 8+ 版本提供支持。

3. Shenandoah 垃圾回收器

Shenandoah 是与 ZGC 类似的一个低延迟垃圾回收器,它同样支持 并发标记并发整理。Shenandoah 主要用在需要极低停顿的环境中。

特点

  • 低停顿:像 ZGC 一样,Shenandoah 通过减少 STW 停顿来优化性能。
  • 内存碎片管理:通过并发整理,Shenandoah 可以减少内存碎片。

优点

  • 在大内存系统和实时应用中表现出色。
  • 适合对低停顿要求高的应用场景。

缺点

  • 支持的 JDK 版本较少。
  • 仍在优化阶段,性能上有时不如 G1。

三、三色标记法:现代 GC 算法的基础

三色标记法是现代垃圾回收算法(如 CMS、G1、ZGC、Shenandoah)背后的核心技术。它的基本思想是:

  • 白色:表示不可达的对象,会被回收。
  • 灰色:表示已标记但子对象未扫描。
  • 黑色:表示已标记且所有子对象扫描完毕。

为什么使用三色标记法?

  • 解决了并发标记中的"漏标"问题。
  • 通过写屏障(Write Barrier)解决了"黑色对象引用白色对象"的问题。

四、总结:GC 算法的演进与优化

在 Java 的垃圾回收算法中,JDK 1.8 之前的常见算法主要依赖 标记-清除、标记-整理复制算法 。这些算法虽然简单,但面临 内存碎片回收效率停顿时间 等问题。

现代的 G1、ZGC、Shenandoah 等算法则采用了 三色标记法并发标记低停顿优化 ,使得大内存、高并发应用能够更高效地进行垃圾回收,特别是 低延迟实时性要求 高的应用。

对于新技术的理解

  • ZGC 和 Shenandoah :代表了 低延迟、高并发 的未来方向,适合大内存、低停顿的场景。
  • G1 和 CMS :仍然广泛应用于传统系统,尤其是对于 可控的停顿时间堆内存管理 的场景。
相关推荐
就起这名行不行2 小时前
一天训练即SOTA!LLaVA-1.5:多模态AI的“性价比之王”全解析
算法
yuer20252 小时前
我把 GPT 当成 Runtime 用:只用一个客户端,跑一个可控、可审计的投资决策 DEMO
算法
鲅鱼饺子2 小时前
PyTorch|BatchNorm 的两种方差
算法
栀秋6662 小时前
面试常考的最长递增子序列(LIS),到底该怎么想、怎么写?
前端·javascript·算法
l1t2 小时前
在duckdb 递归CTE中实现深度优先搜索DFS
sql·算法·深度优先·duckdb·cte
陈陈爱java3 小时前
RRT建模
算法
猿饵块3 小时前
python--锁
java·jvm·python
智算菩萨3 小时前
摩擦电纳米发电机近期进展的理论脉络梳理:从接触起电到统一建模与能量转换
linux·人工智能·算法
xiaolang_8616_wjl3 小时前
c++超级细致的基本框架
开发语言·数据结构·c++·算法