如何在Java中发现内存泄漏(例如,使用JHat)?我尝试在JHat中加载堆转储,以了解基本情况。但是,我不明白如何才能找到根引用(参考)或其他名称。基本上,我可以说有几百兆字节的哈希表条目([java.util.HashMap$Entry或诸如此类的东西]),但是地图在整个地方都被使用.有没有什么方法可以搜索大型地图,或者找到大型对象树的一般根?
编辑: Ok,到目前为止,我已经阅读了答案,但让我们简单地说,我是一个廉价的混蛋(这意味着我更感兴趣的是学习如何使用JHat而不是支付JProfiler)。而且,JHat总是可用的,因为它是JDK的一部分。当然,除非JHat没有办法,只有蛮力,但我不敢相信会是这样。
此外,我认为我无法实际修改(添加所有映射大小的日志记录)并运行足够长的时间,以便我注意到漏洞。
发布于 2008-09-02 18:49:35
我使用以下方法查找Java中的内存泄漏。我已经成功地使用了jProfiler,但我相信任何具有图形化功能的专门工具(差异更容易以图形形式进行分析)都能工作。
基本上,分析应该从最大的正面差异开始,比如,对象类型,并找出是什么导致这些额外的对象留在内存中。
对于在多个线程中处理请求的web应用程序,分析变得更加复杂,但是仍然适用一般的方法。
我做了很多项目,特别是为了减少应用程序的内存占用,这种通用的方法,通过一些特定于应用程序的调整和技巧,总是工作得很好。
发布于 2008-09-11 08:29:56
这里的发问者,我不得不说,获得一个不需要5分钟就能回答任何点击的工具,可以更容易地找到潜在的内存泄漏。
由于人们建议使用几种工具(我在JDK和JProbe试用版中只尝试了visual ),所以我建议在Eclipse上构建一个免费/开放源码工具,内存分析器(有时被称为SAP内存分析器)可以在http://www.eclipse.org/mat/上使用。
这个工具真正酷的地方在于,当我第一次打开堆转储时,它对堆转储进行了索引,这使得它可以显示像保留堆这样的数据,而无需等待每个对象5分钟(几乎所有操作都比我尝试过的其他工具快很多)。
当您打开转储时,第一个屏幕显示一个饼形图,其中包含最大的对象(包括保留的堆),您可以快速地导航到大到舒适的对象。它也有一个可能的泄漏嫌疑人,我认为可以派上用场,但由于导航对我来说已经足够了,我并没有真正进入它。
发布于 2008-09-02 18:30:42
工具是一个很大的帮助。
然而,有时您无法使用工具:堆转储太大,以致于工具崩溃,因此您试图在某些只有shell访问权限的生产环境中对机器进行故障排除,等等。
在这种情况下,了解hprof转储文件的方式会有所帮助。
寻找网站开始。这向您展示了哪些对象使用的内存最多。但是,对象并不是按类型合并在一起的:每个条目还包含一个“跟踪”ID。然后,您可以搜索该“跟踪nnnn”,查看分配对象的堆栈的前几帧。通常,一旦我看到分配对象的位置,我就会发现一个bug,然后就完成了。另外,请注意,您可以使用-Xrunhprof选项来控制堆栈中记录了多少帧。
如果您签出了分配站点,并且没有发现任何错误,您就必须开始从其中一些活动对象向根对象反向链接,以找到意外的引用链。这是一个工具真正有用的地方,但是您可以手工完成同样的事情(嗯,使用grep)。不只是一个根对象(即不受垃圾收集约束的对象)。线程、类和堆栈框架充当根对象,它们强烈引用的任何内容都是不可收集的。
要执行链接,请在堆转储部分查找带有错误跟踪id的条目。这将带您进入OBJ或ARR条目,它以十六进制显示唯一的对象标识符。搜索所有出现的id,找出谁对该对象有强烈的引用。沿着这些路径中的每一条向后走,直到找到漏洞所在为止。明白为什么工具这么方便了吗?
静态成员是内存泄漏的累犯。事实上,即使没有工具,也值得花几分钟时间查看代码中的静态Map成员。地图能变大吗?有什么东西能清理它的条目吗?
https://stackoverflow.com/questions/40119
复制相似问题