java - 为什么 Java CMS 垃圾收集器不允许使用的堆大小增长到可用堆大小?

标签 java garbage-collection g1gc

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

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

enter image description here

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

最佳答案

简短的回答是,当堆填满时,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. 有一些更新的收集器旨在更好地处理“满”堆。

关于java - 为什么 Java CMS 垃圾收集器不允许使用的堆大小增长到可用堆大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64205297/

相关文章:

java - LibGDX Stage vs SpriteBatch 绘制游戏

java - 使上传方法返回字符串 "the uploaded file url"

c# - 请问 GC.SuppressFinalize 有什么实质性影响吗?

java - G1 收集器不执行完整 GC

java - 如何使用 "-Xlog:heap*=debug" "-Xlog:gc*=debug"从 GC 正确读取日志的某些部分

Java G1 : Monitoring for memory leaks in production

java - 如何避免使用jpa2 criteriaBuilder.like中的输入 "%"

java - 如何使用 IntelliJ Idea 15 调试 JSP 文件(断点不起作用)

r - R中的垃圾收集com对象

java - 用垃圾收集语言实现垃圾收集器有意义吗