比较Java内存堆转储:针对Java桌面应用程序的内存分析

10
这是一个更具体的问题,是对我最近提出的另一个问题的跟进。对于这个问题的正确答案也将为之前的问题赢得一个正确答案(因为那个问题仍然悬而未决)!
基本上,我有一个存在内存泄漏问题的Java桌面应用程序。我正在使用NetBeans IDE中的内存分析器来分析内存问题。到目前为止,我已经采取了以下步骤:
1. 将一个新的内存分析器附加到NetBeans项目上 2. 在几个精心选择的代码行上定义分析点,并设置它们以触发内存堆转储 3. 以分析模式运行应用程序
这样做的最终结果是,我在磁盘上保存了几个内存转储文件(*.hprof)。NetBeans IDE允许我浏览这些内存转储文件的内容(基本排序和搜索),甚至让我“遍历堆”,通过查看每个实例内包含的引用以及其他对象对每个实例的引用来了解情况。这一切都很好,到目前为止,我已经能够识别出1或2个相当明显的内存泄漏问题,并解决了大约15%的问题。
然而,目前我使用的方法依赖于在特定时间点创建关于哪些对象不应该在内存中的假设,然后进行调查。我现在想要的是一种比较两个独立堆转储的方法:基本上,我有两个堆转储,它们应该几乎相同,因为应用程序已经恢复到相同的状态。
然而,一个是在内存泄漏之前,另一个是在内存泄漏之后,所以它们显然是不同的。如果我能够使用工具来比较这两个堆转储,而不是像现在这样手动比较,那么我就不需要依赖假设来确定泄漏发生的位置,而可以让工具为我识别它们。
对于我来说,这很重要,因为这个特定应用程序涉及的类和实例数量非常庞大(分别为700+和数百万)。
NetBeans IDE的分析器能够做到这一点吗?
如果不能,是否有其他工具能够执行这个任务?
3个回答

30

还有一个免费的、带图形界面的工具可用于此任务:VisualVM。它可以让你获取多个堆转储文件,并要求你将其中一个与另一个进行比较,以列表的形式显示不同之处,并且使用 每个元素所占用内存的图形表示方式。此外,与 jhat 相比,交互式浏览堆的差异要 更加舒适

VisualVM 1.4.4 compare capability


2
如果给我的回答投了反对票的人能够解释一下为什么,那就太好了。谢谢。 - Daniel Warmuth
2
我已经使用VisualVM获取了几个堆转储文件,现在该如何比较它们? - 11101101b
1
请解释如何做到这一点,特别是VisualVM版本和一些截图会有所帮助。 - stackoverflower
1
显然,这个功能不再可用。 - Consec
2
它已经被移动到堆转储屏幕内“类”顶部右侧的位置。 - Carcigenicate
显示剩余5条评论

16
你可以使用jhat工具。具体来说,查看我引用的页面上的选项(-baseline baseline-dump-file),该页面说明如下:
“指定一个基线堆转储文件。两个堆转储中具有相同对象ID的对象将被标记为不是“new”。其他对象将被标记为“new”。在比较两个不同的堆转储时,这很有用。”
在比较两个堆转储时,这可能会有所帮助。

需要两个堆转储文件来自应用程序的同一次运行(这似乎对 bguiz 来说不是问题)。 - Stephen Denne
@broschb,+1,谢谢 - 这对我很有用!我对JHAT唯一的问题是它的界面是通过一个相当静态的网页进行的,不太用户友好。话虽如此,能够使用“对此对象的引用”遍历堆转储,并能够使用“新实例/包括子类”筛选这些内容,正是我想要的! - bguiz

4
YourKit可以比较堆转储文件。请参考此链接了解更多信息。

答案包含一个失效的链接。请考虑将链接替换为yourkit的内容,以防止由于网站重构导致的死链接(https://www.yourkit.com/docs/java/help/compare_snapshots.jsp)。 - ebonnet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接