为什么';Java CMS垃圾收集器是否允许使用的堆大小增长到可用的堆大小?

为什么';Java CMS垃圾收集器是否允许使用的堆大小增长到可用的堆大小?,java,garbage-collection,g1gc,Java,Garbage Collection,G1gc,我正在测试G1GC和CMS垃圾收集器之间的差异。运行相同的程序会产生不同的堆大小用法(可能与预期的一样) 下图显示了G1GC(左)与CMS GC(右)的对比。G1GC设法运行整个程序,而当使用CMS时,会引发outOfMemoryException 因此,我的问题是:为什么CMS不允许使用的堆大小达到可用的堆大小?当10GB可用时,堆大小在8.00GB处停止增长,出现内存不足异常。简单的回答是,当堆充满时,CMS不如G1GC那样管理内存。这是CMS被逐步淘汰的原因之一 一个稍微长一点的答案是C

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

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


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

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

一个稍微长一点的答案是CMS中的2GB未使用空间保留用于疏散伊甸园空间次要(复制)地面军事系统中的物体。相比之下,G1GC似乎能够在终身空间填满时调整(缩小)伊甸园空间

请注意,这实际上可能是不现实基准的产物。在典型应用程序中,次要集合将成功删除大多数新对象。在您的基准测试中,看起来几乎所有的东西都是可以访问的,所以大部分分配的对象最终都会在永久空间中

你能做些什么

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

  • 您可以更改或减小Eden空间的大小:特别是调整NewSize和MaxNewSize。然而,这对于正常的工作负载来说是不利的。这很容易导致年轻对象过早使用,从而增加CMS收集器上的负载

  • 有一些较新的收集器设计用于更好地处理“完整”堆


  • MaxNewSize
    NewSize
    只有在您同时禁用了
    G1
    的自适应策略时才有意义,这是您很少(如果有的话)想做的事情。@Eugene-我刚才说的是CMS案例。(但不是说这是个好主意……)