美文网首页
垃圾回收的时候怎么解决错标和漏标问题

垃圾回收的时候怎么解决错标和漏标问题

作者: 越努力越幸运阳 | 来源:发表于2024-11-14 16:04 被阅读0次

1. CMS 垃圾回收器解决漏标和错标的方法

CMS(Concurrent Mark-Sweep)是一种并发标记的垃圾回收器。它使用 三色标记法 来区分对象状态,并通过增量更新(Incremental Update)重新标记(Remark)阶段解决并发标记带来的漏标和错标问题。

三色标记算法概述

三色标记法将对象划分为三种颜色,以跟踪其状态:

  • 白色:未访问的对象,可能是垃圾。
  • 灰色:已访问,但它的引用对象还未全部扫描。
  • 黑色:已访问且其引用对象也已全部扫描。

在标记阶段,CMS 会将所有对象从白色变为灰色,最终变为黑色,这样可以保证所有存活对象被标记为黑色。漏标和错标问题在并发标记时出现的原因如下:

  • 漏标:应用线程在标记阶段新创建的对象引用关系可能被漏掉,导致对象被错误地标记为垃圾。
  • 错标:应用线程在标记阶段将白色对象的引用添加到黑色对象中,这样可能导致白色对象未被标记而被当作垃圾。

CMS 解决错标问题:增量更新(Incremental Update)

增量更新用于防止错标,具体如下:

  • 在标记阶段,若应用线程将一个白色对象的引用添加到一个黑色对象中,CMS 会将该白色对象重新标记为灰色,确保它被标记。
  • 通过这样的方法,CMS 可以防止引用从黑色对象指向白色对象而导致的错标。
举例说明:

假设有对象 AB,其中 A 已被标记为黑色,B 尚未标记(为白色):

  1. 应用线程在并发标记阶段为 A 添加了对 B 的引用。
  2. 按照三色标记算法,B 仍为白色,但增量更新会监控这一新增的引用关系,将 B 改为灰色。
  3. 这保证了 B 会在后续标记中被扫描并标记,避免 B 被误认为垃圾。

CMS 解决漏标问题:重新标记(Remark)阶段

重新标记(Remark)阶段是一次短暂停顿(STW)操作,用于确保并发标记期间产生的新对象引用关系被扫描,避免漏标。

  • 在重新标记阶段,垃圾回收线程会暂停应用线程,将并发标记期间产生的新引用对象进行补充标记。
  • 通过这个阶段,CMS 确保不会漏标任何在标记阶段新增的存活对象。
举例说明:

假设并发标记开始时,堆中的对象关系如下:

  • A -> B -> C

在并发标记阶段中:

  1. 应用线程在 A 上新增了指向 D 的引用。
  2. 在重新标记阶段,D 将被检查并标记为灰色,随后扫描 D 的所有引用。
  3. 这样,D 及其引用的所有对象都被正确标记,避免漏标。

2. G1 垃圾回收器解决漏标和错标的方法

G1 采用一种称为 原始快照(Snapshot-At-The-Beginning, SATB) 的技术来解决漏标和错标问题。G1 使用原始快照来追踪在标记阶段开始时所有存活对象的引用关系,确保它们被标记为存活。

三色标记算法在 G1 中的应用

在 G1 中也使用三色标记法,通过原始快照的记录,可以确保对象不会被漏标或错标。

  • 错标问题:G1 使用 原始快照(SATB) 来避免错标。在并发标记阶段,任何对象在标记开始时是存活的(即在原始快照中),就会被标记为灰色,即便引用关系在标记阶段发生变化。
  • 漏标问题:G1 使用 最终标记(Final Remark) 阶段来扫描并标记在并发标记期间新创建或修改的对象引用。

G1 解决错标问题:原始快照(SATB)

在原始快照(SATB)机制下,G1 会在标记开始时记录所有可达对象(即存活对象),形成一个“快照”。在标记过程中,即使引用关系发生变化,G1 会继续标记在快照中记录的所有对象,确保原始可达对象不被误判为垃圾。

举例说明:

假设在标记阶段开始时有对象关系:

  • A -> B -> C
  1. 在标记开始时,ABC 都被记录为可达对象。
  2. 如果在标记过程中,应用线程将 A 的引用移除,导致 A 无法通过新引用关系访问到 BC
  3. 由于 SATB 记录了原始快照,G1 会继续扫描 BC,确保它们被标记为存活,避免错标。

G1 解决漏标问题:最终标记(Final Remark)

G1 使用 最终标记阶段(Final Remark) 来解决漏标问题。在并发标记期间,新创建的对象或引用关系会被 G1 记录并在最终标记阶段扫描,确保没有对象被漏标。

举例说明:

假设在并发标记过程中,新的对象引用关系如下:

  • D 被新增,且 A -> D
  1. 在最终标记阶段(STW 短暂停顿),G1 会扫描 D,将其标记为灰色,随后扫描 D 的引用。
  2. 这样,G1 可以确保在并发标记期间产生的新对象不会被漏掉。

总结

CMS 的方法

  • 错标:通过 增量更新 方法,在标记阶段动态跟踪对象间的新引用关系,确保白色对象重新变为灰色,避免错标。
  • 漏标:通过 重新标记(Remark) 阶段,扫描并标记标记阶段新增的引用对象,防止漏标。

G1 的方法

  • 错标:通过 原始快照(SATB) 方法,记录标记开始时的所有可达对象,确保引用关系变化后,这些对象仍被视为存活,避免错标。
  • 漏标:通过 最终标记(Final Remark) 阶段,标记并发标记阶段新增的对象引用关系,确保所有存活对象都被扫描。

CMS 和 G1 的 漏标错标 处理方式各有优缺点,具体如下:


CMS 的方式:增量更新(Incremental Update)+ 重新标记(Remark)

优点

  1. 低复杂度

    • 增量更新机制简单直接,只需要监控应用线程的新增引用,并重新标记目标对象为灰色即可。
    • 重新标记阶段虽然需要短暂 STW,但算法简单可靠。
  2. 实时性较好

    • 增量更新在并发标记阶段执行,与应用线程协同工作,减少对应用线程的干扰。
  3. 成熟稳定

    • 增量更新和重新标记已经被广泛应用于多种垃圾回收器,算法逻辑清晰、实现成熟。

缺点

  1. 高开销

    • 增量更新需要实时跟踪应用线程的修改操作,会增加写屏障的开销。
    • 如果应用线程频繁更新引用关系,会导致增量更新操作频繁,从而降低效率。
  2. 重新标记需要 STW

    • 重新标记阶段虽然耗时较短,但仍然会暂停所有应用线程,对实时性有一定影响。
  3. 对内存占用不敏感

    • CMS 更加关注回收时间,但对内存利用率不敏感。在高内存压力场景下,容易导致老年代内存不足。

G1 的方式:原始快照(SATB)+ 最终标记(Final Remark)

优点

  1. 准确性高

    • SATB 通过在标记阶段开始时记录“原始快照”,确保所有存活对象不会因为引用变化而被误标为垃圾,从根本上避免错标问题。
  2. 并发性能好

    • SATB 在并发标记阶段完成大部分标记工作,最终标记阶段只是对少量新增引用对象进行补充扫描,减少了 STW 时间。
  3. 适应复杂场景

    • SATB 的“快照”机制可以适应高并发和复杂对象引用变化的场景,尤其是在大内存、多核环境下表现更优。
  4. 整合年轻代和老年代

    • G1 能统一处理年轻代和老年代的内存分配和回收,提升了内存利用率。

缺点

  1. 较高的实现复杂度

    • SATB 需要维护原始快照,写屏障逻辑复杂,增加了实现和调试难度。
    • 实现 SATB 需要额外的内存空间来存储快照数据。
  2. 写屏障开销

    • SATB 需要在每次对象引用变更时记录引用关系,会增加写屏障的时间开销,尤其是高频引用更新的场景可能导致性能下降。
  3. 对 STW 敏感

    • 最终标记阶段(Final Remark)仍需要短暂停顿(STW),如果堆内存巨大或应用线程繁忙,STW 时间可能会变长。

优缺点对比总结

特性 CMS G1
漏标处理 重新标记(Remark),简单但需短暂 STW 最终标记(Final Remark),精准且 STW 时间短
错标处理 增量更新(Incremental Update),低开销 原始快照(SATB),避免复杂引用错标
实时性 增量更新实时性较好,但重新标记需暂停 并发性能较好,适合大内存场景
复杂度 算法简单,成熟稳定 实现复杂,需维护原始快照
写屏障开销 相对较低,依赖引用关系更新频率 较高,尤其在高频引用变更时
内存适应性 对老年代内存利用率敏感,可能出现内存不足 整合年轻代和老年代,提升内存利用率

适用场景对比

  • CMS 适用场景

    • 实时性要求较高,但对象引用更新频率较低的场景。
    • 中小型堆内存场景(如 ≤ 4GB)。
  • G1 适用场景

    • 大内存(如 ≥ 4GB)、多核 CPU 环境下。
    • 对延迟敏感的场景,尤其是需要控制 STW 时间的业务。

相关文章

  • 三色标记

    一、并法标记期间出现的问题 1)漏标:需要处理,不然误回收 2)多标:浮动垃圾,下次回收; 二、漏标的解决方案 并...

  • CMS,G1垃圾回收器中的三色标记

    G1并发标记阶段修改对象引用关系会导致的两个问题:错标:不会影响程序,但是会造成浮动垃圾。漏标:漏了需要检查的对象...

  • JAVA垃圾回收

    JAVA垃圾回收 时间:20180307 问题: 如何判定对象为垃圾对象引用计数法可达性分析法 如何回收回收策略标...

  • G1垃圾收集器之SATB

    简书 占小狼转载请注明原创出处,谢谢! openjdk下载 传送门 对象漏标 垃圾回收的并发标记阶段,gc线程和应...

  • 三色标记法与读写屏障

    前言 本文主要介绍了三色标记法的基本思路、多标导致的浮动垃圾、漏标的处理方案(读写屏障)等。 1. 垃圾回收的简单...

  • JVM-垃圾回收

    JVM的垃圾回收机制指的是对堆中的垃圾对象进行回收。那么我将从三个方面来进行学习和整理,即: 对象被判定为垃圾的标...

  • 《垃圾回收的算法与实现》第2章GC标记-清除算法

    《垃圾回收的算法与实现》第2章GC标记-清除算法 垃圾回收系列连载: 第 1 章 学习GC之前 第 2 章 GC标...

  • 珍惜资源 爱我国土

    在街道上,处处贴着低碳环保, 废物 回收。现在,连垃圾桶上,都标着可回收和不可回收,这意味着我们国家...

  • JVM垃圾收集器

    七大垃圾收集器 GC算法(可达性分析,复制,标清,标整)是内存回收的方法论,垃圾收集器就是这些方法论的落地实现: ...

  • 垃圾回收总结

    内存垃圾回收主要是解决3个问题 哪些内存需要回收 what 何时回收 when 怎么回收 how 哪些需要回收 程...

网友评论

      本文标题:垃圾回收的时候怎么解决错标和漏标问题

      本文链接:https://www.haomeiwen.com/subject/xuojjjtx.html