为什么JVM完整GC需要停止世界?

ced*_*ics 51 garbage-collection jvm

我被问到这个问题,我刚回答"因为JVM需要移动对象",但后来我用Google搜索,似乎找不到任何合理的答案.

Ale*_*zin 69

首先,维基百科的垃圾收集文章真的很好读.

说到.

一般情况下,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 mark-sweep-compact集合.

还有G1,它是MSC的增量变化.您可以在我的博客中阅读有关HotSpot JVMGC算法的更多信息.

  • 根据此 Oracle 页面 https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/cms.html#concurrent_mark_sweep_cms_collector,CMS 收集器在并发收集周期中两次暂停应用程序,包括初始标记暂停和备注暂停。如果碎片太多,没有足够的块,则会导致第三次暂停。 (2认同)

Pie*_*rte 9

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

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

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