OutOfMemoryError有 8种类型。在这种情况下,JVM堆中发生5种类型的OutOfMemoryError。
-
Java heap space
-
GC overhead limit exceeded
-
Requested array size exceeds VM limit
-
Permgen space
-
Metaspace
剩下的 3 types of OutOfMemoryError 发生在堆外内存:
-
Unable to create new native thread
-
Kill process or sacrifice child
-
reason stack_trace_with_native_method
Tools
在这里我们想推荐两种重要的诊断内存泄漏的工具:
- GCeasy**
GCeasy是一款通用的垃圾收集日志分析器,它具有分析和检测垃圾收集日志文件中的内存问题的智能。使用此工具,您将能够检测应用程序是否遭受内存泄漏。这是一个在线工具;您不必下载或安装它。
- Eclipse MAT(http://www.eclipse.org/mat/)**
Eclipse MAT是功能强大的JVM堆转储分析工具。当处理大型堆转储时,Eclipse MAT是最佳选择。您可以从此位置下载Eclipse MAT。以下是一些重要的Eclipse MAT技巧,可以提高您的生产力。
程序
以下是诊断内存泄漏的步骤:
步骤0:验证内存是否在泄漏
在军队中,有一句名言: 不要相信任何人。在诊断生产问题时,这非常适用。由于当前的热度,其他工程师可能会得出一个错误的结论,即没有内存问题时内存正在泄漏。因此,诊断的第一步是确认内存是否确实在泄漏。要确认这一点,您需要做两件事:
1.在日志文件或标准错误中,对grep进行流传输,是否 打印了java.lang.OutOfMemoryError。当分配的内存饱和时,JVM将显示此错误消息。
2.将您的垃圾收集日志文件上传到GCEasy。它具有智能功能,可以确定应用程序中的内存是否正在泄漏。
如果您从任何一个来源获得确认,请继续进行下一步。如果不是这样,您的应用程序可能会遇到其他问题,而不是内存泄漏
步骤1:捕获heap dump
heap dump是Java进程内存的快照。快照包含有关快照创建时有关堆中Java对象和类的信息。
当应用程序处于正常状态时,您需要从应用程序中捕获heap dump。通常,仅在应用程序启动后几分钟或几小时后才开始发生内存泄漏。因此,在启动您的应用程序之后,让该应用程序占用10 -15分钟的流量,然后捕获heap dump。
提示1:
这是捕获heap dump的分步说明 (https://blog.gceasy.io/2015/08/14/how-to-capture-heap-dump-jmap/)
提示2:
最好在生产环境中捕获heap dump(除非在测试环境中,您可以镜像确切的生产流量模式)。流量类型及其流量在内存中创建的对象的类型和数量中起主要作用。
提示3:
请注意,根据堆大小,捕获heap dump会花费时间,从几秒钟到几分钟不等。因此,当您从生产环境捕获heap dump时,请禁用到要捕获heap dump的JVM实例的流量。这将帮助您避免任何客户影响。
步骤2:捕获有问题的堆转储
让您的应用程序运行,直到开始出现内存问题。一旦内存问题开始浮出水面,请再次捕获heap dump。现在的问题是,我怎么知道应用程序是否出现内存问题?通常,当内存问题开始发生时,您会注意到以下症状之一:
- CPU消耗可能开始飙升
2.应用程序可能无响应
- java.lang.OutOfMemoryError字符串将打印在您的应用程序日志文件或标准错误流中
进行适当的监视/警报。一旦开始出现这些症状,请捕获heap dump。
提示位4:
有时,当应用程序遇到内存问题时,您将无法捕获heap dump。在这种情况下,可以在内存问题开始出现之前捕获heap dump(虽然不理想)
将步骤1中捕获的heap dump上载到Eclipse MAT。现在记下占用内存的前5个对象。大多数时候(如果不是一直),由于前5个对象之一而导致内存泄漏。
现在,将步骤2中捕获的heap dump上载到Eclipse MAT。记下前5个对象。如果其中任何一个显示出显着增加,则表明该对象正在泄漏。现在您知道了哪些对象正在泄漏。Eclipse MAT可以选择为您提供这些对象的引用。如果遍历这些引用,您将能够找出导致该内存泄漏的对象/方法/代码行。
在大多数内存泄漏中,诊断是一个痛苦的过程。修复它可能变得非常琐碎。有了这些知识,什么是泄漏对象以及谁在创建对象,您应该能够解决内存泄漏的根本原因。
网友评论