如何查找 Java 内存泄漏

2022-08-31 07:42:34

如何在Java中发现内存泄漏(例如,使用JHat)?我试图在JHat中加载堆转储以进行基本检查。但是,我不明白我应该如何能够找到根引用(ref)或它所称的任何内容。基本上,我可以说有几百兆字节的哈希表条目([java.util.HashMap$Entry或类似的东西),但是到处都是地图......有没有办法搜索大型地图,或者找到大型对象树的一般根?

[编辑]好吧,到目前为止,我已经阅读了答案,但让我们说我是一个廉价的混蛋(这意味着我对学习如何使用JHat比支付JProfiler更感兴趣)。此外,JHat始终可用,因为它是JDK的一部分。当然,除非JHat没有办法,只有蛮力,但我不敢相信会是这样。

另外,我不认为我能够实际修改(添加所有地图大小的日志记录)并运行它足够长的时间,以便我注意到泄漏。


答案 1

我使用以下方法来查找Java中的内存泄漏。我使用jProfiler取得了巨大的成功,但我相信任何具有绘图功能的专用工具(差异更容易以图形形式分析)都可以工作。

  1. 启动应用程序并等待它进入“稳定”状态,此时所有初始化都已完成并且应用程序处于空闲状态。
  2. 多次运行怀疑产生内存泄漏的操作,以允许进行任何与缓存、数据库相关的初始化。
  3. 运行 GC 并拍摄内存快照。
  4. 再次运行该操作。根据操作的复杂性和处理的数据大小,操作可能需要运行多次到多次。
  5. 运行 GC 并拍摄内存快照。
  6. 运行 2 个快照的差异并对其进行分析。

基本上,分析应该从最大的正差异开始,比如对象类型,并找出导致这些额外对象粘在内存中的原因。

对于在多个线程中处理请求的Web应用程序,分析变得更加复杂,但是一般方法仍然适用。

我做了相当多的项目,专门用于减少应用程序的内存占用,这种通用方法具有一些特定于应用程序的调整和技巧,始终效果很好。


答案 2

这里的提问者,我不得不说,获得一个不需要5分钟就可以回答任何点击的工具,可以更容易地找到潜在的内存泄漏。

由于人们建议使用几种工具(自从我在JDK和JProbe试用版中获得visual wm以来,我只尝试过visual wm),我应该建议在Eclipse平台上构建一个免费/开源的工具,即 http://www.eclipse.org/mat/ 上可用的内存分析器(有时称为SAP内存分析器)。

这个工具真正酷的地方在于,当我第一次打开它时,它索引了堆转储,这允许它显示保留堆等数据,而无需为每个对象等待5分钟(几乎所有操作都比我尝试过的其他工具快得多)。

打开转储时,第一个屏幕会显示一个饼图,其中包含最大的对象(计算保留的堆),并且可以快速导航到要大的对象以获得舒适感。它还有一个查找可能的泄漏嫌疑人,我可以派上用场,但由于导航对我来说足够了,我没有真正进入它。