ChatGPT解决这个技术问题 Extra ChatGPT

为什么JVM full GC 需要stop-the-world?

我认为这是因为 JVM 需要移动对象,对吗?

从有关垃圾收集的维基百科页面查看此处en.wikipedia.org/wiki/…

2
2240

首先,Garbage Collection article at wikipedia 非常适合阅读。

一般来说,GC 不需要 Stop-the-World 暂停。有些 JVM 实现(几乎)没有暂停(例如 Azul Zing JVM)。每当 JVM 要求 STW 收集垃圾时,取决于它使用的算法。

Mark Sweep Compact (MSC) 是 HotSpot 默认使用的流行算法。它以 STW 方式实现,分为 3 个阶段:

MARK - 遍历活动对象图以标记可达对象

SWEEP - 扫描内存以查找未标记的内存

COMPACT - 重新定位标记的对象以对可用内存进行碎片整理

在堆中重定位对象时,JVM 应该更正对该对象的所有引用。在重定位过程中,对象图不一致,这就是为什么需要 STW 暂停。

并发标记扫描 (CMS) 是 HotSpot JVM 中的另一种算法,它不利用 STW 暂停来收集旧空间(与完整收集不完全相同)。

CMS 正在利用写屏障(每次在 Java 堆中写引用时触发)来实现 MARK 的并发版本并且不使用 COMPACT。缺乏压缩可能会导致碎片,如果后台垃圾收集速度不够快,应用程序仍然会被阻塞。在这些情况下,CMS 将回退到 STW 标记-扫描-紧凑收集。

还有 G1,它是 MSC 的增量变体。您可以在我的博客中阅读有关 GC algorithms in HotSpot JVM 的更多信息。


多亏了 RedHat,又出现了另一种 GC 算法openjdk.java.net/projects/shenandoah
根据此 Oracle 页面 docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/…,CMS 收集器在并发收集周期中暂停应用程序两次,包括初始标记暂停和重新标记暂停。而如果碎片太多,没有足够的块,就会导致第三次停顿。
a
amanuel2

使用吞吐量 GC,JVM 需要 STW 暂停以释放尽可能多的内存。只有使用这样的停顿才是最有效的。

使用低暂停收集器 (CMS),您可以同时清理老年代,而不会暂停您的应用程序。缺点是老年代变得支离破碎。如果它太碎片化并且需要压缩,则会发生 Full GC (STW)。但是,您始终可以调整您的应用程序,以免获得任何 Full GC。

G1 GC 是一个特例。它当前的主要目标是在堆上具有低碎片,同时仍然是并发的(如 CMS)。当它无法达到这个目标时,JVM 也会恢复到 STW 暂停,以便完全清理和压缩堆。


L
Ludwig Wensauer

stop-the-world 保证不会分配新对象,并且在收集器运行时对象不会突然变得不可访问。

优点是它比增量垃圾收集更容易实现和更快。


在 GC 将其标记为可访问后,对象变得不可访问并不是什么大问题。这是正确的,只是将内存回收延迟了一个 GC 周期。一个更严重的问题是在 GC 期间分配了新对象,并且唯一的引用存储在已经访问过的对象中——然后该对象将被错误地回收。然而,这并不是一个无法解决的问题。事实上,从 70 年代就已经解决了。
C
Community

在几乎任何垃圾收集方案中,即使在大多数最小化暂停的方案中,都需要一个短暂的 stop-the-world 阶段来扫描堆栈上的引用。 this answer 中的详细说明。增量和并发算法努力将这些暂停降至最低,但在大多数情况下仍然存在。

实际上,甚至有一些移动/压缩方法不需要在移动物体时停止世界(想到断奏)