Tomcat java.lang.OutOfMemoryError: GC overhead limit exceeded

Tomcat java.lang.OutOfMemoryError: GC overhead limit exceeded

我们试图将我们的应用程序从 OC4J 迁移到 Tomcat 7.0。该应用程序在 OC4J 上运行良好,但在 tomcat 中,当 运行 对 10 个用户进行负载测试时,性能会受到影响。我们收到这些错误,应用程序不再响应。

---java.lang.OutOfMemoryError: GC overhead limit exceeded 

Exception in thread "ajp-bio-8009-exec-231" java.lang.OutOfMemoryError: GC overhead limit exceeded 
Exception in thread "ContainerBackgroundProcessor[StandardEngine[Catalina]]" java.lang.OutOfMemoryError: GC overhead limit exceeded 

Exception in thread "ajp-bio-8009-exec-236" java.lang.OutOfMemoryError: GC overhead limit exceeded 
Exception in thread "ajp-bio-8009-exec-208" java.lang.OutOfMemoryError: GC overhead limit exceeded 
java.lang.OutOfMemoryError: GC overhead limit exceeded 

java.lang.OutOfMemoryError: GC overhead limit exceeded 

Exception in thread "Thread-33" java.lang.OutOfMemoryError: GC overhead limit exceeded 

Exception in thread "ajp-bio-8009-exec-258" java.lang.OutOfMemoryError: GC overhead limit exceeded 

java.lang.OutOfMemoryError: GC overhead limit exceeded

我们尝试了 JAVA_OPTS="-Xms4096m -Xmx8192m。看起来我们仍然得到错误。请建议我们可以尝试的可能选项..

垃圾收集日志

GC 调用次数=593(完整 539): PSYoungGen 总计 701120K,使用 374720K [0x00000007aaab0000, 0x00000007eaf60000, 0x0000000800000000) eden space 374720K,100% 使用 [0x00000007aaab0000,0x00000007c18a0000,0x00000007c18a0000) 来自 space 326400K,已使用 0% [0x00000007d70a0000,0x00000007d70a0000,0x00000007eaf60000) 至 space 339328K,已使用 0% [0x00000007c18a0000,0x00000007c18a0000,0x00000007d6400000) ParOldGen 总计 2796224K,使用 2796223K [0x0000000700000000, 0x00000007aaab0000, 0x00000007aaab0000) 对象 space 2796224K,已使用 99% [0x0000000700000000,0x00000007aaaaffe8,0x00000007aaab0000) PSPermGen 总计 50688K,已用 50628K [0x00000006fae00000, 0x00000006fdf80000, 0x0000000700000000) 对象 space 50688K,99% 使用 [0x00000006fae00000,0x00000006fdf713a8,0x00000006fdf80000) 4482.450:[完整GC [psyounggen:374720k-> 339611k(701120k)] =12=]

你的 permsize 是多少?你能把它增加到 512m

-XX:MaxPermSize=512m

GC Overrhead Limit exceeded 通常意味着应用程序是 'leaking' 内存的某个位置。您的堆内存使用率很高,例如 98/99%,而完整的 GC 可能会回收一两个百分比。它将做的是它将大部分时间花在 GCing 上。 JVM 检查它花费 GC 的频率,如果超过某个限制,就会抛出此错误。

要解决它,您需要检查发生泄漏的位置。通过获取堆转储来执行此操作。您可以为此使用 jmap。一旦你得到它,你应该看到堆的百分比可能主要属于一组对象

We tried JAVA_OPTS="-Xms4096m -Xmx8192m. Looks like we still get the error. Please suggest the possible options that we could try..

这太多了,只会推迟不可避免的事情。


根据您的更新编辑

如我所料,您的 OldGen space 已达到 99%,几乎没有回收。 OldGen space 是放置所有长寿命对象的地方。由于您没有回收一些内存,所有这些对象最终都会被放入 OldGen 中,您将 运行 内存不足。

值得一读的是这里的两行:

ParOldGen total 2796224K, used 2796223K [0x0000000700000000, 0x00000007aaab0000, 0x00000007aaab0000) object space 2796224K, 99% 

Full GC [PSYoungGen: 374720K->339611K(701120K)] [ParOldGen: 2796223K->2796222K(2796224K)] 3170943K->3135834K(3497344K) 

正如我提到的,OldGen 处于 99%,Full GC 仅回收 1KB YounGen35KB OldGen。它将不得不几乎立即再次进行 GC。此时应该是 GCing GB。

所以

获取堆转储并找出这里最大的罪魁祸首。调查这些对象的创建位置以及为什么它们不会变得不可访问。

如果您有关于 how/where 的任何其他问题或为什么让我知道,但目前我没有其他可以告诉您的。

详细消息 "GC overhead limit exceeded" 表明垃圾收集器一直 运行 并且 Java 程序进展非常缓慢。

可以通过两种方式修复 1) 通过抑制 JVM 参数中的 GC 开销限制警告 Ex- -Xms1024M -Xmx2048M -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit

-UseGCOverheadLimit - 参数用于抑制GCOverHead。

2) 通过识别内存泄漏