何时在Java中选择CMS上的SerialGC,ParallelGC,G1?

Sha*_*war 4 java garbage-collection jvm

在Java 9中,G1 GC是默认的垃圾收集器。截至目前,我听说有些人更喜欢CMS垃圾收集器而不是G1GC,因为它看起来不稳定,并且存在一些令人讨厌的错误。

ParallelGC发生了什么(这些天没有嗡嗡声)?有没有什么用例比起CMS / G1,我们更希望使用ParallelGC?

另外,是否存在SerialGC可以执行所有这些并行收集器的情况?

小智 12

您可以阅读文档Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide-Java9

  • 串行收集器

    它最适合单处理器机器,因为它不能利用多处理器硬件,尽管它对于具有小数据集(最多约 100 MB)的应用程序在多处理器上很有用。

  • 并行收集器

    并行收集器也称为吞吐量收集器,它是类似于串行收集器的分代收集器。串行收集器和并行收集器之间的主要区别在于并行收集器具有多个线程,用于加速垃圾收集。并行收集器适用于在多处理器或多线程硬件上运行的具有中型到大型数据集的应用程序。如果你不关心暂停时间而更喜欢吞吐量,这个收集器是最好的。

  • 大多数并发收集器(CMS)

Java9 中不推荐使用此收集器。

此收集器适用于喜欢较短的垃圾收集暂停并且能够与垃圾收集共享处理器资源的应用程序。

  • G1垃圾收集器

    这种服务器式收集器适用于具有大量内存的多处理器机器。它以高概率满足垃圾收集暂停时间目标,同时实现高吞吐量。

概括:

  • 如果应用程序的数据集很小(最多大约 100 MB),则选择带有选项 -XX:+UseSerialGC 的串行收集器。

  • 如果应用程序将在单个处理器上运行并且没有暂停时间要求,则选择带有选项 -XX:+UseSerialGC 的串行收集器。

  • 如果 (a) 峰值应用程序性能是第一优先级并且 (b) 没有暂停时间要求或可以接受一秒或更长的暂停,那么让 VM 选择收集器或使用 -XX:+UseParallelGC 选择并行收集器.

  • 如果响应时间比总吞吐量更重要并且垃圾收集暂停必须保持短于大约一秒,那么选择带有 -XX:+UseG1GC 或 -XX:+UseConcMarkSweepGC 的并发收集器。

问答:

  1. 我听说有些人更喜欢 CMS 垃圾收集器而不是 G1GC,因为它似乎不稳定并且有一些讨厌的错误。

G1 收集器对于大多数应用来说足够稳定。我在许多应用程序中使用了 G1 收集器,并且它们都运行良好。如果可以将java9升级到Java11,效果会更好,bug也更少。

  1. 是否有任何用例让我们更喜欢 ParallelGC 而不是 CMS/G1?

是的。一些需要更多吞吐量并且不关心使用并行收集器的暂停时间的应用程序会更好。例如,批处理任务、离线作业、计算任务。

  1. 另外,有没有 SerialGC 可以执行所有这些并行收集器的情况?

如果你在嵌入式系统上运行 JVM,或者一些有一个或两个 CPU 的系统,串行 GC 会更好。

最后,G1 VS CMS:在大多数情况下,G1可以替代CMS。在这种情况下,你最好使用 G1:

  1. 你有一个很大的堆,比如 16G。暂停时间和堆大小之间存在正相关关系。相反,G1 是增量收集器。
  2. 您有严格的暂停时间要求,并希望暂停时间更可控。就像,您希望暂停时间 <=10 毫秒。


Eri*_*ang 6


串行采集器

主要用于单cpu机。

算法:

它使用单个线程来处理堆,并在任何gc期间执行世界暂停。只是将其视为玩具。

这是客户端级计算机(Windows或单CPU计算机上的32位jvm)的默认设置。


并联收集器

算法:

它使用多个gc线程来处理堆,并在任何gc期间执行停止世界的暂停。

<= Java 8,这是服务器级机器(多CPU类Unix机器或任何64位jvm)的默认设置。


CMS收集器

它旨在消除与并行和串行收集器的完整gc相关的长时间停顿。

算法:

它使用1个或多个gc线程定期扫描旧的一代,并丢弃未使用的对象,暂停时间很短,但使用了更多的cpu时间。


G1收集器

它是低暂停/服务器风格的gc,主要用于大堆(> 4Gb)。

算法:

  • 与CMS类似,它使用多个后台gc线程扫描并清除堆。
  • 它把老一代分成几部分,可以将老一代从一个部分复制到另一个。
    因此,碎片化的可能性较小。

从Java开始9,这是服务器级计算机(多CPU类的Unix计算机或任何64位jvm)的默认设置。


为什么默认使用G1?

尽管可能会降低总体吞吐量,但主要原因是减少了gc暂停时间。

  • 我认为 CMS 和 G1 肯定会起作用。并行可能也足够好了。如果您的应用程序是实时的(例如交易系统),并且需要非常低的暂停,那么使用G1或CMS(对我来说G1是选择),否则您也可以使用并行收集器。对于像这样的小型应用程序来说,这并不重要。可能更重要的是启用 gc 日志轮换,在出现问题时检查它,并且还可以借助 VisualVM、内置命令 jmap、jcmd 等工具。然后根据需要切换收集器。如果你懒得去检查细节,就用G1吧。 (2认同)