超出GC开销限制,但内存充足

时间:2014-03-01 22:11:31

标签: java java-ee

我的JBoss服务器有一个奇怪的问题:抛出的异常:

java.lang.OutOfMemoryError:超出GC开销限制

我寻找内存不足的情况,但内存可用性看起来不错:

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 2147483648 (2048.0MB)
   NewSize          = 2228224 (2.125MB)
   MaxNewSize       = 4294901760 (4095.9375MB)
   OldSize          = 4194304 (4.0MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 16777216 (16.0MB)
   MaxPermSize      = 805306368 (768.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 176816128 (168.625MB)
   used     = 110937856 (105.798583984375MB)
   free     = 65878272 (62.826416015625MB)
   62.741932681616014% used
From Space:
   capacity = 38207488 (36.4375MB)
   used     = 27193584 (25.933822631835938MB)
   free     = 11013904 (10.503677368164062MB)
   71.17344118514151% used
To Space:
   capacity = 40960000 (39.0625MB)
   used     = 0 (0.0MB)
   free     = 40960000 (39.0625MB)
   0.0% used
PS Old Generation
   capacity = 1434451968 (1368.0MB)
   used     = 818386128 (780.4738311767578MB)
   free     = 616065840 (587.5261688232422MB)
   57.052180641575866% used
PS Perm Generation
   capacity = 113246208 (108.0MB)
   used     = 109507808 (104.43478393554688MB)
   free     = 3738400 (3.565216064453125MB)
   96.69887401439526% used

有没有人在看似有足够的内存之前遇到过这个GC异常?

3 个答案:

答案 0 :(得分:3)

这个错误意味着垃圾收集器正在做出惊人的努力,但却做了很少的实际工作,另一个症状是你的应用程序变得很慢,即使它没有执行任何繁重的任务,因为它花费了大部分时间运行GC,但不要只听我的话,大多数JDK都包含许多工具,如jstat,可用于监控GC的行为,

根据oracle docs

  

如果在垃圾收集中花费了太多时间,则并行收集器将抛出OutOfMemoryError:如果超过98%的总时间花在垃圾收集上并且不到2%的堆被恢复,则OutOfMemoryError将是抛出。此功能旨在防止应用程序长时间运行,同时由于堆太小而很少或根本没有进展

幸运的是,他们还说你如何解决它:

  

如有必要,可以通过在命令行中添加选项-XX:-UseGCOverheadLimit来禁用此功能

然而,它会带走错误信息而不是根本原因,看你的内存条件看起来不像你的内存不足,所以增加堆大小也不会有帮助,很可能是问题出在你的代码的某个地方,检查应用程序的大多数内存密集点,寻找你可能创建大量对象而不放弃它们的地方,并找到一种方法来创建那么多或释放尽可能多的当你不再需要它们时,你可以。

答案 1 :(得分:1)

问题出在@CamiloBermúdez身上。

“GC开销限制”机制旨在在运行垃圾收集器时花费太多时间来终止应用程序。

(理由是,如果花费太多时间进行垃圾收集,那就表明JVM“病了”......可能是最终......并且务实的解决方案是“摆脱困境” ”。)

现在你可以关闭GC开销限制机制,但这是一个坏主意。你可能会陷入更糟糕的境地。机制触发的经典原因是你的堆空间不足(某种或那种),并且GC运行得太频繁了。

更好的策略是打开GC日志记录,并且(如果指示)调整GC或跟踪导致过多内存需求的内容。换句话说,跟踪并修复导致GC开销限制触发的根问题。

答案 2 :(得分:0)

尝试使用以下命令行参数:

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size