【问题标题】:Why doesn't the Java CMS Garbage Collector allow the used heap size to grow to the available heap size?为什么 Java CMS 垃圾收集器不允许已用堆大小增长到可用堆大小?
【发布时间】:2021-01-20 02:57:03
【问题描述】:

我正在测试 G1GC 和 CMS 垃圾收集器之间的差异。运行相同的程序会产生不同的堆大小使用情况(可能符合预期)。

下图显示了 G1GC(左)与 CMS GC(右)的对比。 G1GC 设法运行整个程序,而在使用 CMS 时,会引发 outOfMemoryException

因此,我的问题是:为什么 CMS 不允许已用堆大小达到可用堆大小?当 10GB 可用时,堆大小在 8.00GB 时停止增长,并出现内存不足异常。

【问题讨论】:

    标签: java garbage-collection g1gc


    【解决方案1】:

    简短的回答是,当堆填满时,CMS 不如 G1GC 那样管理内存。这是 CMS 被淘汰的原因之一。

    一个稍微长一点的答案是,CMS 中 2GB 的未使用空间是为 Eden 空间的次要(复制)GC 中的疏散对象而保留的。相比之下,G1GC 似乎能够在 Tenured 空间填满时调整(缩小)Eden 空间。

    请注意,这实际上可能是不切实际的基准测试的产物。在典型的应用程序中,次要集合将成功删除大部分新对象。在您的基准测试中,看起来几乎所有内容都保持可达,因此分配的大多数对象最终都在 Tenured 空间中。

    你能做些什么呢?

    1. 切换到 G1GC。在大多数情况下,CMS 更好。 (最终您将别无选择。CMS 在 Java 9 中已弃用,在 Java 14 中已被删除。)

    2. 您可以更改减小 Eden 空间的大小:具体调整 NewSize 和 MaxNewSize。然而,这对于正常的工作量来说是不利的。这很容易导致年轻对象过早地被永久化,这将增加 CMS 收集器的负载。

    3. 有一些较新的收集器旨在更好地处理“满”堆。

    【讨论】:

    • MaxNewSizeNewSize 仅在您还禁用 G1 的自适应策略时才有意义,这很少(如果有的话)您想做的事情。
    • @Eugene - 我在谈论 CMS 案例。 (虽然不是说这是个好主意......)
    猜你喜欢
    • 1970-01-01
    • 2013-09-27
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 2013-11-30
    • 2012-12-07
    相关资源
    最近更新 更多