内存泄漏分析
这个小型系列的第一个博客介绍了如何创建一个非常泄漏的示例应用程序,以便我们可以研究解决服务器应用程序上基于堆的问题的技术。 它展示了Producer-Consumer模式的一个大问题,即消费者代码必须能够至少与生产者一样快(甚至不是更快)从队列中删除项目。 博客以我开始的示例代码结尾,然后坐了下来,同时它泄漏了足够的内存以进行调查。 现在该进行调查了。
如果您阅读本博客的第1部分 ,您将知道泄漏代码是应用程序1的一部分,该应用程序使用Producer Consumer模式在虚拟数据库中记录了股票/股票定单。 编写示例代码包含一个非常明显的缺陷,即OrderRecord
无法跟上OrderFeed
。 这意味着Order
队列变得越来越大,直到最后,应用程序用完了堆空间并崩溃为止。 问题是,看我的简单代码,问题应该很明显,但是如果您以前从未看过代码,并且它是巨大的,复杂的工业强度代码,又没有简单的监视线程来监视队列大小,该怎么办?或其他内部零件? 那你怎么办呢?
他们是发现泄漏应用程序问题所需的三个步骤:
- 转储泄漏的服务器堆。
- 使用堆转储生成报告。
- 分析报告。
您可以使用多种工具来创建堆转储文件。 这些包括:
- 控制台
- 可视化
- eclipse内存分析器工具(MAT)
使用jconsole进行堆转储
将jconsole
连接到您的应用程序。 单击MBeans选项卡,然后打开com.sun.management
包。 然后,单击HotSpotDiagnostic
。 打开“ Operations
然后选择dumpHeap
。 现在,您将看到dumpHeap
操作,该操作dumpHeap
两个参数p0
和p1
。 在p0
编辑框中键入堆转储的文件名,然后按dumpHeap按钮。
使用jvisualvm进行堆转储
连接到示例代码后,右键单击左侧“应用程序”窗格中的应用程序,然后选择“堆转储”。
请注意,如果您与泄漏的服务器具有远程连接,则jvisualvm将转储文件存储在远程计算机的/tmp
目录中(假设它是Unix机器)。 您将必须将该文件通过FTP传输到您的计算机上以进行进一步分析。
使用MAT进行堆转储
尽管jconsole
和jvisualvm是JDK,MAT或内存分析器工具的一部分,但它是基于eclipse的工具,您可以从eclipse org下载
当前版本的MAT需要在您的PC上安装1.6 jdk。 如果您使用的是Java 1.7,请放心,它将为您安装1.6,并且不会破坏您计算机的其余部分和默认的1.7版本。
使用MAT时,只需单击“获取堆转储”并按照说明进行操作即可。
远程连接
这里要注意的是,如果您想弄清楚生产服务器倒塌的原因,那么您可能必须使用JMX进行远程连接,为此,您需要以下命令行选项,我从我以前的博客重复过:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
何时进行堆转储
这需要一点思考和一点运气。 如果过早获得堆转储,那么您将看不到问题,因为它们被合法的,非泄漏的类实例掩盖了; 但是,不要等待太久,因为进行堆转储需要内存,因此进行堆转储的行为可能会导致应用程序崩溃。
最好的主意是将jconsole
附加到您的应用程序并监视其堆,直到看起来即将崩溃为止。 这很容易发现,因为三个堆部分的指示器都是绿色的:
分析堆转储
这就是MAT自身的用途,因为它旨在分析堆转储。 要打开并分析堆转储,请选择“ File | Open Heap Dump
File | Open Heap Dump
。 选择堆转储文件后,现在将为您提供三个选择,如下所示:
选择: 泄漏可疑报告 。 现在,MAT将流失几秒钟,然后生成如下所示的页面:
饼图表明,在这种情况下,存在一个主要的泄漏嫌疑人。 您可能会认为这是一个修复程序,毕竟这是示例代码,您期望什么? 好吧,是的,在这种情况下,它很明显。 怀疑“ a”占用98.7MB,而内存中的其余对象使用其他1.5MB。 在现实情况中,您确实会得到可疑的泄漏饼图,这是事实。
接下来要做的是更深入地挖掘……
该报告的下一部分(如上所示)告诉我们,有一个LinkedBlockingQueue
正在使用98.46%的内存。 要对此进行进一步调查,请单击Details>>
。
这表明问题确实出在我们的orderQueue
,可通过我以前的博客中的三个对象访问: OrderFeed
, OrderRecord
和OrderMonitor
并且正如我们从代码中知道的那样,其中包含一堆Order
对象。
就是这样了; MAT告诉我们,该示例代码具有一个LinkedBlockingQueue
,它用尽了所有示例应用程序的堆空间,从而导致了巨大的问题。 它并没有告诉我们为什么会这样,您真的不能期望它会发生。 就像阿加莎·克里斯蒂 ( Agatha Christie )的赫尔克里·波洛 ( Hercule Poirot)所说的那样,要使用“ ze little grey cell”……
翻译自: https://www.javacodegeeks.com/2013/12/investigating-memory-leaks-part-2-analysing-the-problem.html
内存泄漏分析