为啥垃圾收集器没有比个位数的无堆百分比更快地进行更积极的垃圾收集?

Posted

技术标签:

【中文标题】为啥垃圾收集器没有比个位数的无堆百分比更快地进行更积极的垃圾收集?【英文标题】:Why is garbage collector not doing a more aggressive garbage collection sooner than single digit heap free %?为什么垃圾收集器没有比个位数的无堆百分比更快地进行更积极的垃圾收集? 【发布时间】:2012-10-11 15:12:26 【问题描述】:

这些是我在 WebLogic 11g 中的 Sun Hotspot 1.6 JVM 堆设置:

-Xms10g -Xmx10g -XX:MaxPermSize=256m -XX:+UseParNewGC -XX:ParallelGCThreads=2 -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:ConcGCThreads=2

我在 24 小时的 JVM 堆空闲百分比图中看到的基本上是堆空闲百分比以缓慢的速度下降,直到我们达到大约 9%(大约需要 24 小时)。然后系统运行看起来像一个完整的 gc 并恢复到 97%。

是否有一些我应该添加/修改的设置来告诉 JVM 比当我们得到低于 10% 的堆空闲时更快地执行这个完整的 GC?例如一些比例设置?

它会等到我们达到 9% 的空闲时才会导致问题,但它会使监控/警报变得更加困难。理想情况下,我们希望始终保持高于 30% 的免费,这样如果我们下降到那些个位数,我们就知道存在某种问题,例如内存泄漏。

【问题讨论】:

根据我对 java 垃圾收集的理解,它可以在需要时免费收集。您可以调用 system.gc 手动告诉垃圾收集器您有应该释放的东西,但 gc 不必这样做。 您可以使用命令 System.gc() 手动进行垃圾收集。 您需要查看 Full GC 后使用/释放了多少内存。否则,可用空间对监控没有用处。 System.gc() 没有明确地运行垃圾收集器,它建议它运行。它不是确定性的。 @BestPractices,我建议您更多地考虑这个问题的 why - 我认为您做出了一个错误的假设,即拥有 10G 的空间。泄漏的更好迹象是完整的 GC 无法回收空间,或者随着时间的推移回收的空间量越来越少 - 这不太容易自动监控。 【参考方案1】:

结合其他 *** 文章找到了答案。

-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=N

其中 N 大致是触发完整 GC 的占用百分比。默认值为 ~92,这就是为什么我看到完整的 GC 有 9% 的免费。将它切换到 65 对我的用例有用。一个完整的 GC 发生了 ~ 现在有 35% 的空闲。

【讨论】:

【参考方案2】:

如何删除:-Xms10g 然后监控堆的总大小?这也将导致 gc 更频繁地运行。

如果您的应用真的只使用 300MB 的内存 (3%),那么从 10 GB 分配开始似乎是极端的。

【讨论】:

盒子上有 128GB 的​​内存。还不如使用 10GB 堆运行。有时,拉入应用程序的数据相当可观(以 GB 为单位),因此我们需要额外的开销。我们从默认堆大小开始,然后调整它的大小以解决某些用例中的 OutOfMemory 错误。所以 10gb 的最大大小保持不变。 我不想建议您更改最大设置。我在评论 -Xms10G 这意味着:从分配 10g 开始。没有它,堆会开始变小,然后在需要时增长到 10g。这应该使内存使用监控更加容易

以上是关于为啥垃圾收集器没有比个位数的无堆百分比更快地进行更积极的垃圾收集?的主要内容,如果未能解决你的问题,请参考以下文章

使垃圾收集器更快地放弃[重复]

在啥时候定义变量比进行方法调用更有效?

为啥数字数组,更多数据排序比对象数组更快,Javascript中的数据更少?

垃圾收集器

Garbage First(G1) 垃圾收集器

JVM 内存分配与回收策略