2

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

我随机收到错误

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

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

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

这是我的发现

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

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

4

2 回答 2

1

好吧,即使你得到了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 开销限制

于 2012-06-30T11:20:01.250 回答
0

好吧,您的 GC 线程正在花费 98% 或更多的处理器时间来尝试清理对象。

工厂模式的想法是返回您希望创建的对象的非空实例,这通常通过在实例化后返回相同的实例来完成。

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

如果你确实有 100,000 个会话,那么好好看看创建它们的方法。分解长方法,以便循环和 while 结构由方法调用分隔,以便方法局部变量可以在超出范围时被清理。

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

于 2013-11-18T16:15:54.560 回答