什么时候有人会在多核机器上使用带有 CMS 垃圾收集器的单线程?

When would anyone use a single thread with the CMS Garbage Collector on a multi-core machine?

我是 运行 服务器上的 Apache Storm 拓扑,使用 Java 7 JVM。我一直在考虑对 JVM 进行一些调整,并注意到它目前正在使用并发标记和清除 (CMS) 垃圾收集器。这是有道理的,因为服务器有 32 个内核,虽然它是 运行 个具有此设置的 JVM,但只有 运行 4 个这样的 JVM,少于 32 个内核。

但是,我注意到我们 运行 设置 CMSConcurrentMTEnabled 的垃圾收集器已 关闭 。默认设置是 on,这让我想知道为什么在其他线程可用时有人会选择使用单个线程进行并发垃圾收集。假设其他线程可用,在什么情况下使用该设置有意义?

(编辑以获取有关我当前情况的更多详细信息,希望能得到答案):

JVM 似乎 运行 内存不足,重复执行次要 GC,每次大约需要 9 秒,并最终崩溃。没有 OutOfMemoryError 被抛出,这让我感到困惑。次要 GC 每次清理几 kB,整体使用率在 100% 左右徘徊了很长一段时间。堆大小为 4 GB,因此这些条件应触发 OutOfMemoryError。但是,我担心,对于一个 SO 问题,这是一个非常本地化的情况。

因此,根据 Twitter 和一些邮件列表的专家,Java 6 update 21 中存在一个错误,其中

...CMS won't always free objects with finalizers[.]

解决方法是禁用设置 CMSConcurrentMTEnabled。 (或者使用较新版本的 Java。)我不确定 Java 的哪个版本最先解决了这个问题。

编辑:

在多核机器上使用单线程并没有使用机器的全部功能。

如果你想增加 CMS 的并行 gc 线程数,你可以使用下面的配置。

可以使用命令行选项 -XX:ParallelGCThreads= 控制垃圾收集器线程的数量。

可以在 documentation 文章中找到更多微调选项。

考虑使用 G1GC 代替 CMS。

G1GC 在大堆中变得非常流行 post JDK 7 update 4 release。它可能成为 Java 9 版本中的默认 GC 算法。

通过设置暂停时间目标等目标,您可以提高暂停时间的可预测性。

看看

http://www.oracle.com/technetwork/articles/java/g1gc-1984535.html

http://www.oracle.com/technetwork/tutorials/tutorials-1876574.html