为什么CMS停止世界的初始标记,但不是为了清扫阶段?

时间:2016-09-25 11:25:00

标签: java garbage-collection concurrent-mark-sweep

CMS有4个高级阶段适用于完整GC

  1. 初始标记: - 停止世界(STW)
  2. 并发标记: - 并发运行
  3. 备注: - STW
  4. 并发扫描: - 并发运行
  5. 阅读

    后,我对CMS有了更深入的了解

    http://www.tikalk.com/java/garbage-collection-serial-vs-parallel-vs-concurrent-mark-sweep/https://plumbr.eu/handbook/garbage-collection-algorithms-implementations/concurrent-mark-and-sweep

    我的问题是为什么初始标记阶段是Initial Mark阶段的STW?我们不能将备注阶段作为STW,因为这是对帐的最后阶段。

    同样地,为什么Sweeping phase不是STW,因为它需要压缩,这意味着改变对象的物理位置。因此,如果对象由app和并发引用 线程改变了phsical位置,不会成为问题吗?

    我知道我在这里遗漏了一些东西,但是那是什么?

1 个答案:

答案 0 :(得分:1)

我假设您在Oracle的HotSpot JVM中引用了Concurrent Mark Sweep实现。

初始标记阶段包括扫描年轻空间(任何年轻到旧的参考都是并发标记的根)。备注阶段包括非常相同的操作。

理论上,您可以省略STW作为初始标记,因为它可以同时扫描并丢失少量root的风险(将在最终备注期间以任何方式恢复)。虽然这里有缺点

  • 由于年轻的集合正在移动对象,因此扫描内存可能不准确。老收藏家和年轻收藏家之间的同步将变得更加复杂。
  • 如果在不准确的初始标记期间会遗漏某些根,则备注可能会变得非常长,因为它涉及遍历可从新发现的根目录到达的对象。

扫描不需要STW,因为它不紧凑。 CMS不会在并发周期中压缩旧空间。

Here is my article explaining nature and asymptotics of CMS GC pauses