Java 为什么我们需要“一个”呢;清扫;在标记清理垃圾收集期间?

Java 为什么我们需要“一个”呢;清扫;在标记清理垃圾收集期间?,java,garbage-collection,Java,Garbage Collection,假设我们正在使用mark-sweep垃圾收集算法,如果我们能够将内存分配标记为“可回收”,这还不够吗?程序难道不知道“可回收”内存基本上是未使用的内存,可以在请求时分配吗?如图所示,“可回收”区块与“未使用”区块之间的物理区别是什么: 标记在标记阶段,所有可从Java线程、本机句柄和其他根源访问的对象以及可从这些对象访问的对象等都标记为活动对象。这个过程识别并标记所有仍在使用的对象,其余的可以视为垃圾 扫描-在扫描阶段,遍历堆以查找活动对象之间的间隙。这些间隙记录在自由列表中,并可用于新对象分配

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

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

扫描-在扫描阶段,遍历堆以查找活动对象之间的间隙。这些间隙记录在自由列表中,并可用于新对象分配

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

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

扫描-在扫描阶段,遍历堆以查找活动对象之间的间隙。这些间隙记录在自由列表中,并可用于新对象分配

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

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

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

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

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

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


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

有一个标记和不清除收集器。你读过吗?也许通过比较和对比这些方法,你会发现answer@Michael这些“标记和不清除收集器”仅将清除延迟到分配器必须搜索未标记内存时,这在技术上与清除相同。由于此类算法通常由失败的分配触发,因此分配器必须在标记后立即搜索第一个可用的块,即使不一定给出惰性。所以它只是同一事物的另一个名称。有一个标记和不清除收集器。你读过吗?也许通过比较和对比这些方法,你会发现answer@Michael这些“标记和不清除收集器”仅将清除延迟到分配器必须搜索未标记内存时,这在技术上与清除相同。由于此类算法通常由失败的分配触发,因此分配器必须在标记后立即搜索第一个可用的块,即使不一定给出惰性。所以它只是同一事物的另一个名称。为什么它甚至需要扫描阶段呢?它不能在做标记阶段的时候创建自由列表吗?@Ryn标记阶段并不像看上去那么简单,有多个子阶段。阅读这里@Ryn你如何在不知道将什么放入列表的情况下构建一个免费列表?为什么它甚至需要扫描阶段?它不能在做标记阶段的时候创建自由列表吗?@Ryn标记阶段并不像看上去那么简单,有多个子阶段。在这里阅读@Ryn你如何建立一个免费的列表而不知道将什么放入列表中?