OutOfMemoryError 内存溢出问题排查

Posted 抓手

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OutOfMemoryError 内存溢出问题排查相关的知识,希望对你有一定的参考价值。

OutOfMemoryError的几种情况如下:

java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
java.lang.OutOfMemoryError: request bytes for . Out of swap space
java.lang.OutOfMemoryError: (Native method)


java.lang.OutOfMemoryError: Java heap space

此错误消息不一定意味着内存泄漏。实际上,问题可能与配置问题一样简单。

例如,我负责分析一直产生这种类型的OutOfMemoryError的应用程序。经过一番调查后,我发现罪魁祸首是阵列实例化,因为需要太多的内存;在这种情况下,并不是应用程序的错,而是应用程序服务器依赖于默认的堆太小了。我通过调整解决了这个问题。

在其他情况下,特别是对于长期存在的应用程序,该消息可能表明我们无意中持有对象的引用,从而阻止垃圾收集器清理它们。这时Java语言等同于内存泄漏。 (注意:应用程序调用的API也可能无意中持有对象引用。)

这些 Java堆空间 OOM的另一个潜在来源是使用finalizers。如果类具有finalize方法,则在垃圾收集时该类型的对象不会被回收。而是在垃圾收集之后,稍后对象将排队等待最终确定。在Sun实现中,finalizers由执行。如果finalizers线程无法跟上finalization队列,那么Java堆可能会填满并且可能抛出OOM。

java.lang.OutOfMemoryError: PermGen space

此错误消息表明已满。永久代是存储类和方法对象的堆的区域。如果应用程序加载了大量类,则可能需要使用-XX:MaxPermSize选项增加永久代的大小。

java.lang.String对象也存储在永久代中。 java.lang.String类维护一个字符串池。调用实习方法时,该方法检查池以查看是否存在等效字符串。如果是这样,它由实习方法返回;如果没有,则将字符串添加到池中。更准确地说,java.lang.String.intern方法返回一个字符串的规范表示;结果是对该字符串显示为文字时将返回的同一个类实例的。如果应用程序实例化大量字符串,则可能需要增加永久代的大小。

注意:您可以使用jmap -permgen命令打印与永久生成相关的统计信息,包括有关内部化String实例的信息。

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

此错误表示应用程序(或该应用程序使用的API)尝试分配大于堆大小的数组。例如,如果应用程序尝试分配512MB的数组但最大堆大小为256MB,则将抛出此错误消息的OOM。在大多数情况下,问题是配置问题或应用程序尝试分配海量数组时导致的错误。

java.lang.OutOfMemoryError: request bytes for . Out of swap space

此消息似乎是一个OOM。但是,当本机堆的分配失败并且本机堆可能将被耗尽时,HotSpot VM会抛出此异常。消息中包括失败请求的大小(以字节为单位)以及内存请求的原因。在大多数情况下,是报告分配失败的源模块的名称。

如果抛出此类型的OOM,则可能需要在操作系统上使用故障排除实用程序来进一步诊断问题。在某些情况下,问题甚至可能与应用程序无关。例如,您可能会在以下情况下看到此错误:

操作系统配置的交换空间不足。
系统上的另一个进程是消耗所有可用的内存资源。

由于本机泄漏,应用程序也可能失败(例如,如果某些应用程序或库代码不断分配内存但无法将其释放到操作系统)。

java.lang.OutOfMemoryError: (Native method)

如果您看到此错误消息并且堆栈跟踪的顶部框架是本机方法,则该本机方法遇到分配失败。此消息与上一个消息之间的区别在于,在JNI或本机方法中检测到Java内存分配失败,而不是在Java VM代码中检测到。

如果抛出此类型的OOM,您可能需要在操作系统上使用实用程序来进一步诊断问题。

Application Crash Without OOM

有时,应用程序可能会在从本机堆分配失败后很快崩溃。如果您运行的本机代码不检查内存分配函数返回的错误,则会发生这种情况。

例如,如果没有可用内存,malloc系统调用将返回NULL。如果未检查malloc的返回,则应用程序在尝试访问无效的内存位置时可能会崩溃。根据具体情况,可能很难定位此类问题。

在某些情况下,致命错误日志或崩溃转储的信息就足以诊断问题。如果确定崩溃的原因是某些内存分配中缺少错误处理,那么您必须找到所述分配失败的原因。与任何其他本机堆问题一样,系统可能配置了但交换空间不足,另一个进程可能正在消耗所有可用内存资

以上是关于OutOfMemoryError 内存溢出问题排查的主要内容,如果未能解决你的问题,请参考以下文章

Java学习---内存溢出的排查经历

java内存溢出

遇到Java内存溢出(OOM)时,这样排查

内存溢出

强如 Disruptor 也发生内存溢出?

OOM排查