【问题标题】:Why do we need the "sweep" during mark-sweep Garbage Collection?为什么我们需要在标记清扫垃圾收集期间进行“清扫”?
【发布时间】:2020-05-29 00:09:24
【问题描述】:

假设我们正在使用标记清除垃圾收集算法,如果我们能够将内存分配标记为“可回收”,这还不够吗?难道程序不知道“可回收”内存基本上是可以在请求时分配的未使用内存吗?如图所示,“可回收”块与“未使用”块之间的物理差异是什么:

【问题讨论】:

  • 有一种标记和不扫描收集器。你读过它吗?也许通过比较和对比这些方法,您会找到答案
  • @Michael 这些“mark-and-don't-sweep 收集器”只是将清扫推迟到分配器必须搜索未标记内存时,这在技术上与清扫相同。鉴于此类算法通常由分配失败触发,因此分配器必须在标记后立即搜索第一个可用块,即使是惰性也不一定给出。所以它只是同一事物的另一个名称。

标签: java garbage-collection


【解决方案1】:

标记 - 在标记阶段,所有可从 Java 线程、本机句柄和其他根源访问的对象都被标记为活动的,以及可从这些对象访问的对象等等.此过程识别并标记所有仍在使用的对象,其余的可以视为垃圾。

清扫 - 在清扫阶段,遍历堆以查找活动对象之间的间隙。这些间隙记录在空闲列表中,可供新的对象分配使用。

未使用与可回收空间 - 未使用的空间只不过是活动块之间的间隙,这些间隙是由于未使用/可回收对象的垃圾收集而产生的,压缩阶段会将未使用的块移动到最后。比较发布图片中的两个图表。

【讨论】:

  • 为什么它甚至需要扫描阶段呢?难道它不能在标记阶段建立空闲列表吗?
  • @Ryn Mark 阶段并不像看起来那么简单,有多个子阶段。在这里阅读plumbr.io/handbook/…
  • @Ryn 您如何在不知道将什么放入列表中的情况下构建免费列表?
【解决方案2】:

扫描步骤只是延迟停止世界事件的“另一种”方式。当然,理论上这是一件好事。 在标记时,还要跟踪这个“空闲”空间,其中已识别出死对象。因此,您可以在下次分配时使用这些列表中的信息。

问题是,当您仅使用sweep 时,堆不是“紧凑”的,因此当没有连续的可用空间进行分配时(基于这些空闲列表信息),仍然会执行压缩阶段。

我的最后一点是CMS 已被弃用,没有人支持,因此了解它的作用可能很有趣,但并不真正有价值;因为其他 GC 的做法不同。

【讨论】:

    猜你喜欢
    • 2014-11-08
    • 1970-01-01
    • 2015-04-10
    • 2015-07-13
    • 2011-12-11
    • 2018-06-10
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    相关资源
    最近更新 更多