我正在研究一个基于Java的大系统中潜在的内存泄漏(或至少是内存浪费)。 JVM的最大堆大小为5 GB,并且2-3GB堆使用量是应用程序的预期基线。 (可能有更高的峰值)
在我正在调查的重载场景中,堆被填满了。使用“Eclipse MemoryAnalyzer Tool”分析堆转储显示(毫不奇怪)堆已完全用完。
MAT显示了2个潜在的泄漏候选者,两者大致保留了2.5GB:java.lang.Thread和系统中的域对象,该对象在系统中的事务处理期间广泛使用。但是,从Thread实例可以访问所有这些域对象(不足为奇)。毕竟,这些线程正在处理事务。因此,归因于java.lang.Thread的2.5 GB几乎完全是由那些域对象引起的。这里不足为奇。
列出所有java.lang.Thread实例的对象树,并总结所有线程的保留堆,得到2.5 GB的保留堆。
如果无法从java.lang.Thread实例访问堆,那么我应该在哪里寻找填充堆所需的其他2.5 GB? - 终结器队列中没有任何内容 - GC没有大量无法访问的对象
我认为另一种提出这个问题的方法是:“我如何找到所有从java.lang.Thread实例无法访问的对象?也许是OQL查询?”,另一个问题是:“什么样的对象是否有一些java.lang.Thread实例无法访问,除了终结器队列中的对象和未引用的GC中的对象?“
答案 0 :(得分:4)
我也遇到了我们网站内存泄漏的问题,
使用提供大量信息的yourkit java profiler,凭借其能力,您可以获得更广泛的图像,使用所有内存。
您可以使用上述工具找到一个很棒的教程Find Java Memory Leaks。
你的问题,
“哪些类型的对象无法从java.lang.Thread的实例访问,除了终结器队列中的对象和未引用的对象等待GC?”
有四种对象,
除了这些JVM还使用本机内存,其信息可以在IBM Heap and native memory use by the JVM和Thanks for the memory找到,根据YourKit,JVM Memory Structure具有非堆内存,根据它们的定义是< / p>
此外,JVM还有堆以外的内存,称为非堆内存。它在JVM启动时创建并存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码,以及实习字符串。
答案 1 :(得分:3)
由于额外的记忆没有在MAT中显示,因此很难知道建议什么。如果有些(甚至大部分)是你已经知道的事情,我很抱歉,我只是想把所有想到的东西整合在一起。
<强> FindBugs的强>
FindBugs是一个静态分析工具,它将扫描您的代码,寻找常见的反模式和问题,并为您提供一个很好的报告。它确实可以解决潜在内存和资源泄漏的许多原因。
手动转储
你可以尝试使用像jmap或visualvm这样的东西来手动进行堆转储以进行分析,看看你是否得到了让eclipse这样做的不同结果:
http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jmap.html
http://java.dzone.com/articles/java-heap-dump-are-you-task
分析器怪癖
内存分析器常见问题解答:
http://wiki.eclipse.org/MemoryAnalyzer/FAQ
表示:
症状:以交互方式监视内存使用情况时,使用的堆大小比MAT报告的大得多。
在索引创建期间,Memory Analyzer会删除无法访问的对象,因为各种垃圾收集器算法往往会留下一些垃圾(如果对象太小,移动并重新分配地址是昂贵的)。但是,这应该不超过3%到4%。如果您想知道删除了哪些对象,请按照此处的说明启用调试输出:MemoryAnalyzer / FAQ #Enable_Debug_Output
另一个原因可能是堆转储未正确写入。如果通过jmap写入堆转储,则特别是较旧的VM(1.4,1.5)可能会出现问题。
启用调试输出将允许您查看那里发生的事情,并确认该区域没有任何奇怪的内容。
其中一些提示可能相关
http://eclipsesource.com/blogs/2013/01/21/10-tips-for-using-the-eclipse-memory-analyzer/
答案 2 :(得分:1)
使用JProfiler并按类别打破堆对象数 - 查找哪个类有很多实例并在那里开始搜索。
您还可以在短时间内拍摄几个快照,并比较两个堆转储以查看在此期间创建的对象。如果您知道某个操作导致了问题并且您想要忽略所有后台JVM对象噪声并且只检查增量,那么这一点尤其方便。
我已经非常成功地使用它来查找内存泄漏。它不是免费的,但值得许可费。
仅供参考:我与JProfiler没有任何关系。
答案 3 :(得分:0)
也许您应该在数据库连接器代码或ORM中查找内存泄漏。因为如果在不关闭游标时使用原始连接库,则可能会导致内存泄漏。我的第二个想法也与数据库连接器有关。因为其中一些(可能不是你的)使用下面的本机代码,这是此泄漏的来源。由于大量的并发使用对我来说很敏感。如果需要,你可以检查一下。
答案 4 :(得分:0)
Since the extra memory is not showing in MAT it's hard to know what to suggest.
这不是真的。 MAT显示无法访问的对象。只需转到de Preferences并选中启用此选项的复选框。 MAT重启后,您将看到这些对象的详细信息。当然,GC的根将无法使用。