一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Java 垃圾回收算法中的标记清除算法

时间:2026-07-10 10:20:52 编辑:袖梨 来源:一聚教程网

标记-清除算法是Java最基础的垃圾回收算法,分标记和清除两阶段:标记阶段从GC Roots出发遍历可达对象并标记,清除阶段回收未标记对象内存,但产生碎片且需Stop-The-World暂停。

标记清除算法是 Java 垃圾回收中最基础的算法之一,它分为“标记”和“清除”两个阶段,核心思想简单直接:先找出所有存活对象并打上标记,再统一回收未被标记的对象所占内存。

标记阶段:如何识别存活对象

从 GC Roots(如栈帧中的局部变量、静态变量、JNI 引用等)出发,沿着引用链递归遍历所有可达对象,并对每个可达对象设置标记位。这个过程采用深度优先或广度优先遍历,确保不遗漏也不重复标记。

  • GC Roots 必须严格限定范围,否则可能误判存活对象
  • 标记过程需要暂停用户线程(Stop-The-World),影响应用响应时间
  • 标记位通常记录在对象头中,占用极小额外空间

清除阶段:回收未标记内存

遍历整个堆内存,将未被标记的对象所占空间释放,但不进行内存整理。这意味着空闲内存可能以碎片形式分散在堆中。

  • 清除操作本身开销较小,只需更新空闲链表或内存页状态
  • 会产生内存碎片,可能导致后续大对象无法分配,即使总空闲空间足够
  • 无法处理循环引用问题——不过现代 JVM 的可达性分析已天然解决该问题

实际应用中的局限与优化方向

标记清除算法很少单独用于新生代或老年代的主回收器,更多作为其他算法(如 CMS、ZGC 的部分阶段)的基础组件。它的主要短板在于碎片化和 STW 时间不可控。

立即学习“Java免费学习笔记(深入)”;

  • CMS 收集器曾使用该算法实现老年代并发回收,但因碎片问题最终被 G1 取代
  • G1 不直接使用标记清除,而是结合标记整理(Mark-Compact)来避免碎片
  • 如果发现频繁 Full GC 且老年代碎片严重,可能是标记清除类回收器在起作用,需考虑切换到 G1 或 ZGC

对比其他算法的关键差异

与复制算法相比,标记清除不需要额外的半区空间,适合老年代这种存活率高的场景;与标记整理算法相比,它省去了移动对象的开销,但牺牲了内存连续性。

  • 复制算法适合新生代——存活对象少,复制成本低
  • 标记整理适合老年代中要求高内存利用率的场景
  • 标记清除折中了空间与时间,但对内存分配模式敏感

热门栏目