文章插图
在《JAVA虚拟机规范》的规定里,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生 OutOfMemoryError 异常的可能 。
本篇主要包括如下 OOM 的介绍和示例:
- java.lang.StackOverflowError
- java.lang.OutOfMemoryError: Java heap space
- java.lang.OutOfMemoryError: GC overhead limit exceeded
- java.lang.OutOfMemoryError-->Metaspace
- java.lang.OutOfMemoryError: Direct buffer memory
- java.lang.OutOfMemoryError: unable to create new native thread
- java.lang.OutOfMemoryError:Metaspace
- java.lang.OutOfMemoryError: Requested array size exceeds VM limit
- java.lang.OutOfMemoryError: Out of swap space
- java.lang.OutOfMemoryError:Kill process or sacrifice child
我们常说的 OOM 异常,其实是 Error
文章插图
一. StackOverflowError1.1 写个 bug
public class StackOverflowErrorDemo { public static void main(String[] args) { javaKeeper(); } private static void javaKeeper() { javaKeeper(); }}
上一篇详细的介绍过JVM 运行时数据区
,JVM 虚拟机栈是有深度的,在执行方法的时候会伴随着入栈和出栈,上边的方法可以看到,main 方法执行后不停的递归,迟早把栈撑爆了
Exception in thread "main" java.lang.StackOverflowError at oom.StackOverflowErrorDemo.javaKeeper(StackOverflowErrorDemo.java:15)
文章插图
1.2 原因分析
- 无限递归循环调用(最常见原因),要时刻注意代码中是否有了循环调用方法而无法退出的情况
- 执行了大量方法,导致线程栈空间耗尽
- 方法内声明了海量的局部变量
- native 代码有栈上分配的逻辑,并且要求的内存还不小,比如 java.net.SocketInputStream.read0 会在栈上要求分配一个 64KB 的缓存(64位 linux)
- 修复引发无限递归调用的异常代码,通过程序抛出的异常堆栈,找出不断重复的代码行,按图索骥,修复无限递归 Bug
- 排查是否存在类之间的循环依赖(当两个对象相互引用,在调用toString方法时也会产生这个异常)
- 通过 JVM 启动参数 -Xss 增加线程栈内存空间,某些正常使用场景需要执行大量方法或包含大量局部变量,这时可以适当地提高线程栈空间限制
Java 堆内存的 OOM 异常是实际应用中最常见的内存溢出异常 。
2.1 写个 bug
/** * JVM参数:-Xmx12m */public class JavaHeapSpaceDemo { static final int SIZE = 2 * 1024 * 1024; public static void main(String[] a) { int[] i = new int[SIZE]; }}
代码试图分配容量为 2M 的 int 数组,如果指定启动参数 -Xmx12m,分配内存就不够用,就类似于将 XXXL 号的对象,往 S 号的 Java heap space 里面塞 。Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at oom.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:13)
2.2 原因分析- 请求创建一个超大对象,通常是一个大数组
- 超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值
- 过度使用终结器(Finalizer),该对象没有立即被 GC
- 内存泄漏(Memory Leak),大量对象引用没有释放,JVM 无法对其自动回收,常见于使用了 File 等资源没有回收
- 如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制
推荐阅读
- 产品风险评估报告怎么写 淘宝店铺风险分析
- 再见HTML ! 用纯Python就能写一个漂亮的网页
- 纯CSS实现轮播图
- 假设你的文案压根没人看
- 如何写出转化率高的爆款文案
- 写在最美的季节,送给径山的冬日散文诗
- 分析2.5万篇博客后,来看看后端程序员每天都在写什么
- 淘宝卖家给买家的好评怎么写 淘宝店铺好评怎么写
- 淘宝申诉说明范例 淘宝侵权申诉内容怎么写
- Ubuntu18.04部署django3.x