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

2024-11-14  本文已影响0人  越努力越幸运阳

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

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

三色标记算法概述

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

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

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

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

举例说明:

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

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

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

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

举例说明:

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

在并发标记阶段中:

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

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

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

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

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

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

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

举例说明:

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

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

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

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

举例说明:

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

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

总结

CMS 的方法

G1 的方法

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),避免复杂引用错标
实时性 增量更新实时性较好,但重新标记需暂停 并发性能较好,适合大内存场景
复杂度 算法简单,成熟稳定 实现复杂,需维护原始快照
写屏障开销 相对较低,依赖引用关系更新频率 较高,尤其在高频引用变更时
内存适应性 对老年代内存利用率敏感,可能出现内存不足 整合年轻代和老年代,提升内存利用率

适用场景对比

上一篇 下一篇

猜你喜欢

热点阅读