java.lang.OutOfMemoryError:GC开销限制超出Spring Hibernate Tomcat 6

java.lang.OutOfMemoryError: GC overhead limit exceeded Spring Hibernate Tomcat 6

我在使用Spring + Hibernate的Web应用程序中遇到问题。

我随机收到错误

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

当web应用程序在tomcat中运行时

我试图获取Heap转储并使用Eclipse MAT对堆转储进行分析

以下是我的发现

对象org.hibernate.impl.SessionFactoryObjectFactory拥有86%的内存,此对象的Fashhashmap实例拥有超过100000个Hashmaps。
在每个Hashmap中都有一个org.hibernate.impl.SessionFactoryImpl的实例,
似乎org.hibernate.impl.SessionFactoryImpl被多次加载并存储在org.hibernate.impl.SessionFactoryObjectFactory的Fashhashmap中

有人可以帮助我找到这个问题的根本原因,并建议一些解决方案来解决这个问题。


好吧,即使你得到那个SessionFactoryObjectFactory holds 86% of the memory,它似乎也不是我的原因。首先,在依赖任何内存分析工具之前,我们应该先了解这个工具如何预测outofmemory问题。
内存工具只是尝试捕获运行该工具后在应用程序中显示的即时HIKES。我很确定你会得到相同的错误日志说但是工具提到的不同原因Catalina web class loader正在访问主要的内存量,这是显而易见的。

所以我只想弄清楚,而不是依赖任何这样的工具(可能在特定的情况/实现中),你试图挖掘你的应用程序源代码并尝试找到不必要的临时对象的创建位置。

出于调试目的,您可以打开JVM选项 - -XX:-PrintGCDetails以查看GC正在收集的内容。

有关详细信息,请参阅这些帖子/参考资料 - http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#Options
java.lang.OutOfMemoryError:超出了GC开销限制


那么你的GC线程正在花费98%或更多的处理器时间来尝试清理对象。

Factory模式的想法是返回您想要创建的对象的非null实例,这通常通过在实例化后返回相同的实例来完成。

现在可能有100,000个不同的会话或诸如此类但我怀疑这是正确的,因此您需要检查您的代码以确保正确地关闭Factory方法调用,并且可能没有缓存本地副本。

如果确实有100,000个会话,那么请仔细查看创建它们的方法。断开长方法,以便通过方法调用分隔循环和while结构,以便可以在范围之外清除方法局部变量。

还要确保这些较小的方法不是最终的,因为编译器会将最终方法拼接成一个堆栈帧作为优化技术。