常? OOM 异常分析
Posted aric2016
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常? OOM 异常分析相关的知识,希望对你有一定的参考价值。
---------作者: 捡?螺的?男孩
常? OOM 异常分析
- 堆溢出
- 栈溢出
- 方法区溢出
- 本机直接内存溢出
- GC overhead limit exceeded
一、堆溢出
Java 堆?于存储对象实例,只要不断地创建对象,并且保证 GC Roots 到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么
在对象数量到达最?堆的容量限制后就会产?内存溢出异常。
原因
- 无法在java堆中分配对象
- 应用程序保存了无法被GC回收的对象
- 应用程序过度使用finalizer
排查解决思路
查找关键报错信息,如java.lang.OutOfMemoryError: Java heap space。
使?内存映像分析?具(如 Eclipsc Memory Analyzer 或者 Jprofiler)对 Dump 出来的堆储存快照进?分析,分析清楚是内存泄漏还是内存溢出。
如果是内存泄漏,可进?步通过?具查看泄漏对象到 GC Roots 的引?链,修复应?程序中的内存泄漏。
如果不存在泄漏,先检查代码是否有死循环,递归等,再考虑? -Xmx 增加堆??。
二、栈溢出
关于虚拟机栈和本地?法栈,在 Java 虚拟机规范中描述了两种异常:
如果线程请求的栈深度?于虚拟机所允许的深度,将抛出 StackOverflowError 异常;
如果虚拟机栈可以动态扩展,当扩展时?法申请到?够的内存时会抛出 OutOfMemoryError 异常。
原因
在单个线程下,栈帧太?,或者虚拟机栈容量太?,当内存?法分配的时候,虚拟机抛出StackOverflowError 异常。
不断地建?线程的?式会导致内存溢出。
排查解决思路
- 查找关键报错信息,确定是 StackOverflowError 还是 OutOfMemoryError;
- 如果是 StackOverflowError,检查代码是否递归调??法等;
- 如果是 OutOfMemoryError,检查是否有死循环创建线程等,通过 - Xss 降低的每个线程栈??的容量。
三、?法区溢出
?法区,(?叫永久代,JDK8 后,元空间替换了永久代),?于存放 Class 的相关信息,如类名、访问修饰符、常量池、字段描述、?法描述等。运?时产??量的类,会填满?法区,造成溢出。
原因
使? CGLib ?成了?量的代理类,导致?法区被撑爆。
在 Java7 之前,频繁的错误使? String.intern ?法。
?量 jsp 和动态产? jsp。
应??时间运?,没有重启。
排查解决思路
- 检查是否永久代空间设置得过?;
- 检查代码是否频繁错误得使? String.intern ?法;
- 检查是否跟 jsp 有关;
- 检查是否使? CGLib ?成了?量的代理类;
- 重启?法,重启 JVM。
四、本机直接内存溢出
直接内存并不是虚拟机运?时数据区的?部分,也不是 Java 虚拟机规范中定义的内存区域。但是,这部分内存也被频繁地使?,?且
也可能导致 OOM。
在 JDK1.4 中新加?了 NIO(New Input/Output) 类,它可以使? native 函数库直接分配堆外内存,然后通过?个存储在 Java 堆中的
DirectByteBuffer 对象作为这块内存的引?进?操作。这样能在?些场景中显著提?性能,因为避免了在 Java 堆和 Native 堆中来回复
制数据。
原因
本机直接内存的分配虽然不会受到 Java 堆??的限制,但是受到本机总内存??限制。
直接内存由 -XX:MaxDirectMemorySize 指定,如果不指定,则默认与 Java 堆最?值(-Xmx 指定)?样。
NIO 程序中,使? ByteBuffer.allocteDirect(capability) 分配的是直接内存,可能导致直接内存溢出。
排查解决思路
- 检查代码是否恰当。
- 检查 JVM 参数 - Xmx,-XX:MaxDirectMemorySize 是否合理。
五、GC overhead limit exceeded
这个是 JDK6 新加的错误类型,?般都是堆太?导致的。
Sun 官?对此的定义:超过 98% 的时间?来做 GC 并且回收了不到 2% 的堆内存时会抛出此异常。
解决方案
- 检查项?中是否有?量的死循环或有使??内存的代码,优化代码。
- 检查 JVM 参数 - Xmx -Xms 是否合理。
- dump 内存,检查是否存在内存泄露,如果没有,加?内存。
六、总结
?种常? OOM 异常:
- java.lang.OutOfMemoryError: Java heap space
- java.lang.OutOfMemoryError: unable to create new native thread
- java.lang.OutOfMemoryError: Metaspace
- java.lang.OutOfMemoryError: Direct buffer memory
- java.lang.OutOfMemoryError: GC overhead limit exceeded
以上是关于常? OOM 异常分析的主要内容,如果未能解决你的问题,请参考以下文章
使用Hive SQL插入动态分区的Parquet表OOM异常分析
使用Hive SQL插入动态分区的Parquet表OOM异常分析