1

我发现这个:

-XX:GCHeapFreeLimit=2 - 定义完全 GC 之后在抛出 OutOfMemoryError 之前可用空间的最小百分比

但是当我尝试在我的应用程序中使用此选项时,我遇到了问题

我的 JVM 的选项是:

-server -d64 -Xss256k
-verbose:gc
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-Xms332m
-Xmx332m
-XX:NewSize=128m
-XX:MaxNewSize=128m

-XX:PermSize=64m
-XX:MaxPermSize=64m
-XX:+DisableExplicitGC
-XX:+UseParNewGC

-XX:ParallelGCThreads=2
-XX:ParallelGCThreads=2
-XX:MaxTenuringThreshold=1
-XX:SurvivorRatio=8
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled
-XX:+CMSClassUnloadingEnabled
-XX:+CMSPermGenSweepingEnabled
-XX:CMSInitiatingOccupancyFraction=60
-XX:+UseCMSInitiatingOccupancyOnly
-XX:GCHeapFreeLimit=40
-XX:GCTimeLimit=70

所以(-XX:GCHeapFreeLimit=40)我想如果在完全 GC 之后,空闲堆大小会小于 40%,我会看到 OOME。但它并没有发生。我有很多类似的日志消息:

[Full GC [CMS2013-08-15T14:20:47.068+0100: [CMS-concurrent-mark: 0.200/0.203 secs] [Times: user=0.38 sys=0.02, real=0.20 secs]
 (concurrent mode failure): 208895K->208895K(208896K), 0.8387700 secs] 326911K->304069K(326912K), [CMS Perm : 35941K->35939K(65536K)], 0.8388880 secs] [Times
: user=0.83 sys=0.00, real=0.84 secs]

我可以看到 (326911-304069)/326911 超过 60%。但我的申请并没有失败。

4

2 回答 2

3

当以下 3 个条件都为真时抛出 OOME 错误(本文来自 Scott Oaks 的 Java 性能调优书)

  1. 在完整 GC 中花费的时间量超过了 -XX:GCTimeLimit=N标志指定的值。默认值为 98(即,如果 98% 的时间用于 GC)。
  2. full GC 回收的内存量小于-XX:GCHeapFreeLimit=N标志指定的值。默认值为 2,这意味着如果在完整 GC 期间释放的堆少于 2%,则满足此条件。
  3. 上述两个条件在连续五个完整的 GC 周期内都成立(该值不可调整)。

在您的情况下,JVM 释放的内存可能少于 60%,但 JVM 可能连续 5 个周期释放的内存少于 60%,或者 JVM 连续 5 个周期在 GC 中花费的时间不超过 70%,或以上组合.

于 2016-04-20T13:38:07.823 回答
1

这不是这个选项的目的。从这里

与 -XX:+UseParallelGC 一起使用有助于防止垃圾回收期间发生内存不足异常。此参数指定垃圾回收期间释放的空间量的下限,以最大堆的百分比表示(默认为 5)。

因此,该选项用于通过使 GC 更具攻击性来潜在地防止OOME。

没有什么理由可以控制 OOME 何时发生,因为它的目的是在堆上没有更多空间可以分配给对象时抛出。人为地让它更早发生没有多大意义。虽然,正如您已经发现的那样,有一些选择,但我认为这违反了班级的合同。您真的想给其他开发人员稍后维护您的代码带来潜在的难题吗?

于 2013-08-15T14:30:29.697 回答