• A+

几种OOM异常分析

OOM为out of memory的简称,称之为内存溢出。

程序中常见的打印有如下几类:

一:

如图:

Java应用程序在启动时会指定所需要的内存大小,其主要被分割成两个不同的部分,分别为Head space(堆空间-Xmx指定)和Permegen(永久代-XX:MaxPermSize指定),

通常来说,造成如上图异常的基本上程序代码问题而造成的内存泄露。这种异常,通过dump+EMA可以轻松定位。(EMA虽功能强大,但对机器性能内存要求极高)

二:

Java.lang.OutOfMemeoryError:GC overhead limit exceeded

如上异常,即程序在垃圾回收上花费了98%的时间,却收集不回2%的空间,通常这样的异常伴随着CPU的冲高。定位方法同上。

三:

Java.lang.OutOfMemoryError: PermGen space(JAVA8引入了Metaspace区域)

永久代内存被耗尽,永久代的作用是存储每个类的信息,如类加载器引用、运行池常量池、字段数据、方法数据、方法代码、方法字节码等。基本可以推断PermGen占用大小取决于被加载的数量以及类的大小。定位方法同上。

还有很多OOM异常,甚至会触发操作系统的OOM killer去杀掉其它进程。

四:

本节主要讨论下面一种OOM,如图

产生这种异常的原因是由于系统在不停地创建大量的线程,且不进行释放。系统的内存是有限的,分配给JAVA应用的程序也是有限的,系统自身能允许创建的最大线程数计算规则:

(MaxProcessMemory-JVMMemory-ReservedOsMemory)/ThreadStackSize

其中

MaxProcessMemory:指的是一个进程的最大内存

JVMMemory :JVM内存

ReservedOsMemory:保留的操作系统内存

ThreadStackSize:线程栈的大小

从公式中可以得出结论,系统可创建线程数量与分配给JVM内存大小成反比。

在java程序中,创建一个线程,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,且系统线程的内存不占用JVMMemory,而占用系统中剩下的内存,即(MaxProcessMemory - JVMMemory - ReservedOsMemory)。

结论很明显:程序创建的线程不可能无限大。

先讨论第一种情况,即经jstack或dump后,线程的数量确在系统要求的阀值内,报上面异常,该如何?

1.参考之前的参数,可以修改两个变量JVMMemory和ThreadStackSize来满足更多线程创建的要求。

-Xss1024k -Xms4096m -Xmx4096m

2.查看是否操作系统限制了可创建线程数量

执行ulimit -u 可以查看当前用户可创建线程量,如果不满足要求,可以通过修改配置文件调整其大小:

相关配置文件在etc/security/limit.d/XX-nproc.conf中

 


注意:本文归作者所有,未经作者允许,不得转载
所属分类:问答

全部评论: 0

    我有话说:
    ×