常? OOM 异常分析

Posted aric2016

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常? OOM 异常分析相关的知识,希望对你有一定的参考价值。

---------作者: 捡?螺的?男孩

常? OOM 异常分析

  • 堆溢出
  • 栈溢出
  • 方法区溢出
  • 本机直接内存溢出
  • GC overhead limit exceeded

一、堆溢出

Java 堆?于存储对象实例,只要不断地创建对象,并且保证 GC Roots 到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么
在对象数量到达最?堆的容量限制后就会产?内存溢出异常。

原因

  • 无法在java堆中分配对象
  • 应用程序保存了无法被GC回收的对象
  • 应用程序过度使用finalizer

排查解决思路

  1. 查找关键报错信息,如java.lang.OutOfMemoryError: Java heap space。

  2. 使?内存映像分析?具(如 Eclipsc Memory Analyzer 或者 Jprofiler)对 Dump 出来的堆储存快照进?分析,分析清楚是内存泄漏还是内存溢出。

  3. 如果是内存泄漏,可进?步通过?具查看泄漏对象到 GC Roots 的引?链,修复应?程序中的内存泄漏。

  4. 如果不存在泄漏,先检查代码是否有死循环,递归等,再考虑? -Xmx 增加堆??。


二、栈溢出

关于虚拟机栈和本地?法栈,在 Java 虚拟机规范中描述了两种异常:

  • 如果线程请求的栈深度?于虚拟机所允许的深度,将抛出 StackOverflowError 异常;

  • 如果虚拟机栈可以动态扩展,当扩展时?法申请到?够的内存时会抛出 OutOfMemoryError 异常。

原因

  • 在单个线程下,栈帧太?,或者虚拟机栈容量太?,当内存?法分配的时候,虚拟机抛出StackOverflowError 异常。

  • 不断地建?线程的?式会导致内存溢出。

排查解决思路

  1. 查找关键报错信息,确定是 StackOverflowError 还是 OutOfMemoryError;
  2. 如果是 StackOverflowError,检查代码是否递归调??法等;
  3. 如果是 OutOfMemoryError,检查是否有死循环创建线程等,通过 - Xss 降低的每个线程栈??的容量。

三、?法区溢出

?法区,(?叫永久代,JDK8 后,元空间替换了永久代),?于存放 Class 的相关信息,如类名、访问修饰符、常量池、字段描述、?法描述等。运?时产??量的类,会填满?法区,造成溢出。

原因

  • 使? CGLib ?成了?量的代理类,导致?法区被撑爆。

  • 在 Java7 之前,频繁的错误使? String.intern ?法。

  • ?量 jsp 和动态产? jsp。

  • 应??时间运?,没有重启。

排查解决思路

  1. 检查是否永久代空间设置得过?;
  2. 检查代码是否频繁错误得使? String.intern ?法;
  3. 检查是否跟 jsp 有关;
  4. 检查是否使? CGLib ?成了?量的代理类;
  5. 重启?法,重启 JVM。

四、本机直接内存溢出

直接内存并不是虚拟机运?时数据区的?部分,也不是 Java 虚拟机规范中定义的内存区域。但是,这部分内存也被频繁地使?,?且
也可能导致 OOM。

在 JDK1.4 中新加?了 NIO(New Input/Output) 类,它可以使? native 函数库直接分配堆外内存,然后通过?个存储在 Java 堆中的
DirectByteBuffer 对象作为这块内存的引?进?操作。这样能在?些场景中显著提?性能,因为避免了在 Java 堆和 Native 堆中来回复
制数据。

原因

  • 本机直接内存的分配虽然不会受到 Java 堆??的限制,但是受到本机总内存??限制。

  • 直接内存由 -XX:MaxDirectMemorySize 指定,如果不指定,则默认与 Java 堆最?值(-Xmx 指定)?样。

  • NIO 程序中,使? ByteBuffer.allocteDirect(capability) 分配的是直接内存,可能导致直接内存溢出。

排查解决思路

  1. 检查代码是否恰当。
  2. 检查 JVM 参数 - Xmx,-XX:MaxDirectMemorySize 是否合理。

五、GC overhead limit exceeded

  • 这个是 JDK6 新加的错误类型,?般都是堆太?导致的。

  • Sun 官?对此的定义:超过 98% 的时间?来做 GC 并且回收了不到 2% 的堆内存时会抛出此异常。

解决方案

  1. 检查项?中是否有?量的死循环或有使??内存的代码,优化代码。
  2. 检查 JVM 参数 - Xmx -Xms 是否合理。
  3. 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 异常分析的主要内容,如果未能解决你的问题,请参考以下文章

Java程序员必备:常见OOM异常分析

使用Hive SQL插入动态分区的Parquet表OOM异常分析

使用Hive SQL插入动态分区的Parquet表OOM异常分析

使用Hive SQL插入动态分区的Parquet表OOM异常分析

深入理解Java虚拟机03:OOM异常

HDFS oiv解析Fsimage OOM异常处理