JVM若是发生的OOM的8种缘由,你能及时想出解决的方法吗

小A:xx服务又宕机了java

小B:歪日,咋搞的,登上去看看咋回事web

小A:又OOM了,不知道哪一个**写的代码,一坨*同样。数组


JVM若是发生的OOM的8种缘由,你能及时想出解决的方法吗



撸Java的同窗,多多少少会碰到内存溢出(OOM)的场景,但形成OOM的缘由倒是多种多样。tomcat

堆溢出app

这种场景最为常见,报错信息:框架

java.lang.OutOfMemoryError: Java heap space

缘由less

一、代码中可能存在大对象分配ide

二、可能存在内存泄露,致使在屡次GC以后,仍是没法找到一块足够大的内存容纳当前对象。工具

解决方法优化

一、检查是否存在大对象的分配,最有可能的是大数组分配

二、经过jmap命令,把堆内存dump下来,使用mat工具分析一下,检查是否存在内存泄露的问题

三、若是没有找到明显的内存泄露,使用 -Xmx 加大堆内存

四、还有一点容易被忽略,检查是否有大量的自定义的 Finalizable 对象,也有多是框架内部提供的,考虑其存在的必要性

永久代/元空间溢出

报错信息:

java.lang.OutOfMemoryError: PermGen space

java.lang.OutOfMemoryError: Metaspace

缘由

永久代是 HotSot 虚拟机对方法区的具体实现,存放了被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等。

JDK8后,元空间替换了永久代,元空间使用的是本地内存,还有其它细节变化:

  • 字符串常量由永久代转移到堆中

  • 和永久代相关的JVM参数已移除

可能缘由有以下几种:

一、在Java7以前,频繁的错误使用String.intern()方法

二、运行期间生成了大量的代理类,致使方法区被撑爆,没法卸载

三、应用长时间运行,没有重启

没有重启 JVM 进程通常发生在调试时,以下面 tomcat 官网的一个 FAQ:

Why does the memory usage increase when I redeploy a web application?

That is because your web application has a memory leak.

A common issue are “PermGen” memory leaks. They happen because the Classloader (and the Class objects it loaded) cannot be recycled unless some requirements are met (). They are stored in the permanent heap generation by the JVM, and when you redeploy a new class loader is created, which loads another copy of all these classes. This can cause OufOfMemoryErrors eventually.

(*) The requirement is that all classes loaded by this classloader should be able to be gc’ed at the same time.

解决方法

由于该OOM缘由比较简单,解决方法有以下几种:

一、检查是否永久代空间或者元空间设置的太小

二、检查代码中是否存在大量的反射操做

三、dump以后经过mat检查是否存在大量因为反射生成的代理类

四、放大招,重启JVM

GC overhead limit exceeded

这个异常比较的罕见,报错信息:

java.lang.OutOfMemoryError:GC overhead limit exceeded

缘由

这个是JDK6新加的错误类型,通常都是堆过小致使的。Sun 官方对此的定义:超过98%的时间用来作GC而且回收了不到2%的堆内存时会抛出此异常。

解决方法

一、检查项目中是否有大量的死循环或有使用大内存的代码,优化代码。

二、添加参数 -XX:-UseGCOverheadLimit 禁用这个检查,其实这个参数解决不了内存问题,只是把错误的信息延后,最终出现 java.lang.OutOfMemoryError: Java heap space。

三、dump内存,检查是否存在内存泄露,若是没有,加大内存。

方法栈溢出

报错信息:

java.lang.OutOfMemoryError : unable to create new native Thread

缘由

出现这种异常,基本上都是建立的了大量的线程致使的,之前碰到过一次,经过jstack出来一共8000多个线程。

解决方法

一、经过 -Xss 下降的每一个线程栈大小的容量

二、线程总数也受到系统空闲内存和操做系统的限制,检查是否该系统下有此限制:

  • /proc/sys/kernel/pid_max

  • /proc/sys/kernel/thread-max

  • maxuserprocess(ulimit -u)

  • /proc/sys/vm/maxmapcount

很是规溢出

下面这些OOM异常,可能大部分的同窗都没有碰到过,但仍是须要了解一下

分配超大数组

报错信息 :

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

这种状况通常是因为不合理的数组分配请求致使的,在为数组分配内存以前,JVM 会执行一项检查。要分配的数组在该平台是否能够寻址(addressable),若是不能寻址(addressable)就会抛出这个错误。

解决方法就是检查你的代码中是否有建立超大数组的地方。

swap溢出

报错信息 :

java.lang.OutOfMemoryError : Out of swap space

这种状况通常是操做系统致使的,可能的缘由有:

一、swap 分区大小分配不足;

二、其余进程消耗了全部的内存。

解决方案:

一、其它服务进程能够选择性的拆分出去

二、加大swap分区大小,或者加大机器内存大小

本地方法溢出

报错信息 :

java.lang.OutOfMemoryError: stack_trace_with_native_method

本地方法在运行时出现了内存分配失败,和以前的方法栈溢出不一样,方法栈溢出发生在 JVM 代码层面,而本地方法溢出发生在JNI代码或本地方法处。

这个异常出现的几率极低,只能经过操做系统本地工具进行诊断,难度有点大,仍是放弃为妙。

相关文章
相关标签/搜索