在这里插入图片描述

Java常用垃圾回收算法详解

在 Java 虚拟机(JVM)中,垃圾回收(Garbage Collection, GC)负责自动管理内存,回收不再使用的对象。以下是常用的垃圾回收算法,我会用故事举例通俗解释:


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

  • 原理
    1. 标记:遍历所有对象,标记哪些是存活对象(被引用的)。
    2. 清除:回收所有未标记的对象(垃圾)。
  • 故事比喻
    想象一个仓库管理员(GC)需要清理仓库。他先给所有有用的货物贴上标签(标记),再把所有没标签的货物扔掉(清除)。
  • 优缺点
    • ✅ 简单直接,不需要移动对象。
    • ❌ 产生内存碎片(就像仓库里留下很多零散空位),可能影响大对象分配。

2. 复制算法(Copying)

  • 原理
    1. 将内存分为两半(From 区和 To 区)。
    2. 将 From 区的存活对象复制到 To 区。
    3. 清空整个 From 区。
  • 故事比喻
    仓库有两间房(A 和 B),管理员先把 A 间有用的货物搬到 B 间,然后一键清空 A 间。
  • 优缺点
    • ✅ 无内存碎片,回收高效。
    • ❌ 浪费一半内存空间(永远有一间房空着)。
  • 应用场景:年轻代(Young Generation)的 Survivor 区(如 Eden + S0/S1)。

3. 标记-整理算法(Mark-Compact)

  • 原理
    1. 标记:标记存活对象。
    2. 整理:将所有存活对象向内存一端移动。
    3. 清理:回收边界外的空间。
  • 故事比喻
    管理员把仓库中有用的货物全部推到一侧码放整齐,然后把另一侧的空地一次性清理干净。
  • 优缺点
    • ✅ 无内存碎片,空间利用率高。
    • ❌ 移动对象成本高("整理"阶段耗时更长)。
  • 应用场景:老年代(Old Generation),如 CMS 或 G1 的某些阶段。

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

  • 原理
    • 分代:将堆内存分为年轻代(Young)和老年代(Old)。
    • 回收策略
      • 年轻代:存活率低 → 用复制算法(快速回收)。
      • 老年代:存活率高 → 用标记-清除标记-整理(减少移动开销)。
  • 故事比喻
    仓库分为新品区(年轻代)和古董区(老年代)。新品区经常大扫除(复制算法),古董区偶尔整理(标记-整理)。
  • 优缺点
    • ✅ 针对性优化,平衡效率与空间。
    • ❌ 实现复杂(需维护分代逻辑)。
  • 应用场景:现代 JVM(如 HotSpot)的默认策略。

5. 分区算法(Region-Based)

  • 原理
    将堆划分为多个小区域(Regions),独立回收。
  • 代表G1 垃圾回收器
  • 故事比喻
    把仓库分成多个小隔间,管理员每次只清理最乱的几个隔间,避免全仓停工。
  • 优点
    • ✅ 可控停顿时间(避免全局 STW)。
    • ✅ 灵活处理不同区域。

总结

算法 适用场景 优点 缺点
标记-清除 老年代(CMS) 简单 内存碎片
复制算法 年轻代(Survivor) 无碎片、高效 浪费 50% 空间
标记-整理 老年代(Serial GC) 无碎片、空间利用率高 移动对象成本高
分代收集 现代 JVM 堆 平衡效率与空间 实现复杂
分区算法(G1) 大堆内存 可控停顿、灵活回收 内存占用稍高

核心思想:没有完美的算法,只有适合场景的策略。JVM 根据对象生命周期特点选择最优组合!
在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐