线上OOM:GC Overhead Limit Exceeded异常是如何排查和解决的?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1494个文字,预计阅读时间需要6分钟。
一、Java内存模型
《Java虚拟机规范》定义了虚拟机的内存结构,包括以下运行时数据区:
1. 方法区(Method Area):存储类信息、常量、静态变量等。
2.虚拟机栈(VM Stack):存储局部变量表、操作数栈、方法出口等信息。
3.本地方法栈(Native Method Stack):用于支持Native方法。
4.堆(Heap):存储对象实例。
5.程序计数器(Program Counter Register,PC寄存器):用于记录当前线程执行的字节码指令地址。
二、运行时数据区详解
1. 方法区(Method Area):包括运行时常量池、字段和方法数据、构造函数表等。
2.虚拟机栈(VM Stack):每个线程有一个虚拟机栈,用于存储局部变量表、操作数栈、方法出口等信息。
3.本地方法栈(Native Method Stack):用于支持Native方法,每个虚拟机栈都有自己的本地方法栈。
4.堆(Heap):存储对象实例,是所有线程共享的。
5.程序计数器(PC寄存器):记录当前线程执行的字节码指令地址,是线程私有的。
一、Java的内存模型
《Java虚拟机规范》规定虚拟机包括以下几个运行时数据区:
- 方法区 - Method Area
- 虚拟机栈 - VM Stack
- 本地方法栈 - Native Method Stack
- 堆 - Heap
- 程序计数器 - Program Counter Register
在不同的JVM运行时实现中可能存在差异
常见的JVM运行时有:
- OracleJDK
- OpenJDK
- IBM J9
- JRocket
- Alibaba Dragonwell
- Tencent Kona
- Graalvm
比如OracleJDK8的方法区区叫元空间,具体不再展开...
不考虑差异性,本文主旨是线上OracleJDK8说明内存溢出出现的场景,排查方式和解决方案
二、内存溢出类型
- StackOverflowError
- OutOfMemoryError
StackOverflowError当线程栈深度超过设置的最大深度,则由虚拟机抛出 OutOfMemoryError当无法通过JVM申请到内存时,则由虚拟机抛出
除了程序计数器外,栈、堆、非堆(直接内存)都可以抛出OOM
常见的异常错误及通用解:
- java.lang.StackOverflowError : Thread Stack space
原因:当线程栈深度超过设置的最大深度,则由虚拟机抛出
解决:
1)使用循环替换递归
2)使用调度器MapReduce思想来实现分之归并
- java.lang.OutOfMemoryError: Java heap space
原因:当前线程无法从JVM申请堆内存空间
解决:
1)具体问题具体分析,当定位到是大对象时,需要优化代码为小对象
2)当定位到是堆内存空间太小,修改VM配置。这里需评估并发量,经过压测和优化后得出
3)优化代码,减少处理耗时,如果是高耗时操作,可以在对象不使用后,去掉局部变量对大对象的引用
4)当定位到是内存泄露,则需要修改泄露代码(通常在引用第三方包出现)
- java.lang.OutOfMemoryError: Requested array size exceeds VM limit
原因:申请数组大小超过JVM允许值,不同JVM版本存在差异
解决:
1) 修改申请数组小大
- java.lang.OutOfMemoryError: GC Overhead Limit Exceeded
原因:当 GC 为释放很小空间占用大量时间时抛出,通常会伴随着CPU100%异常,线上系统严重卡顿
解决:跟Java heap space处理方法一样
- java.lang.OutOfMemoryError: Metaspace
原因:当前线程无法从JVM申请元空间内存,JDK8之后原永久代中的类元数据迁移到元空间(堆 -> 直接内存),常量池继续在堆中
解决:
1)当定位到是元空间设置太小,修改配置
2)当定位到是内存泄露,则修改代码(通常在引用第三方包出现)
- java.lang.OutOfMemoryError: Direct buffer memory
原因:一般是工具为了做零拷贝,直接将数据存储在直接内存中,减少用户态和内核态内存拷贝,当未做内存回收时,空间不释放,抛出异常
解决:
1)定位到直接内存设置太小,修改配置
2)定位到内存泄露未释放内存,则修改异常代码
3)定位到Metaspace未设置大小,该空间内存泄露,则修改异常代码
疑难借助工具排查:
- VisualVM
- Eclipse MAT(Memory Analyzer Tool)
- Alibab Arthas
本文共计1494个文字,预计阅读时间需要6分钟。
一、Java内存模型
《Java虚拟机规范》定义了虚拟机的内存结构,包括以下运行时数据区:
1. 方法区(Method Area):存储类信息、常量、静态变量等。
2.虚拟机栈(VM Stack):存储局部变量表、操作数栈、方法出口等信息。
3.本地方法栈(Native Method Stack):用于支持Native方法。
4.堆(Heap):存储对象实例。
5.程序计数器(Program Counter Register,PC寄存器):用于记录当前线程执行的字节码指令地址。
二、运行时数据区详解
1. 方法区(Method Area):包括运行时常量池、字段和方法数据、构造函数表等。
2.虚拟机栈(VM Stack):每个线程有一个虚拟机栈,用于存储局部变量表、操作数栈、方法出口等信息。
3.本地方法栈(Native Method Stack):用于支持Native方法,每个虚拟机栈都有自己的本地方法栈。
4.堆(Heap):存储对象实例,是所有线程共享的。
5.程序计数器(PC寄存器):记录当前线程执行的字节码指令地址,是线程私有的。
一、Java的内存模型
《Java虚拟机规范》规定虚拟机包括以下几个运行时数据区:
- 方法区 - Method Area
- 虚拟机栈 - VM Stack
- 本地方法栈 - Native Method Stack
- 堆 - Heap
- 程序计数器 - Program Counter Register
在不同的JVM运行时实现中可能存在差异
常见的JVM运行时有:
- OracleJDK
- OpenJDK
- IBM J9
- JRocket
- Alibaba Dragonwell
- Tencent Kona
- Graalvm
比如OracleJDK8的方法区区叫元空间,具体不再展开...
不考虑差异性,本文主旨是线上OracleJDK8说明内存溢出出现的场景,排查方式和解决方案
二、内存溢出类型
- StackOverflowError
- OutOfMemoryError
StackOverflowError当线程栈深度超过设置的最大深度,则由虚拟机抛出 OutOfMemoryError当无法通过JVM申请到内存时,则由虚拟机抛出
除了程序计数器外,栈、堆、非堆(直接内存)都可以抛出OOM
常见的异常错误及通用解:
- java.lang.StackOverflowError : Thread Stack space
原因:当线程栈深度超过设置的最大深度,则由虚拟机抛出
解决:
1)使用循环替换递归
2)使用调度器MapReduce思想来实现分之归并
- java.lang.OutOfMemoryError: Java heap space
原因:当前线程无法从JVM申请堆内存空间
解决:
1)具体问题具体分析,当定位到是大对象时,需要优化代码为小对象
2)当定位到是堆内存空间太小,修改VM配置。这里需评估并发量,经过压测和优化后得出
3)优化代码,减少处理耗时,如果是高耗时操作,可以在对象不使用后,去掉局部变量对大对象的引用
4)当定位到是内存泄露,则需要修改泄露代码(通常在引用第三方包出现)
- java.lang.OutOfMemoryError: Requested array size exceeds VM limit
原因:申请数组大小超过JVM允许值,不同JVM版本存在差异
解决:
1) 修改申请数组小大
- java.lang.OutOfMemoryError: GC Overhead Limit Exceeded
原因:当 GC 为释放很小空间占用大量时间时抛出,通常会伴随着CPU100%异常,线上系统严重卡顿
解决:跟Java heap space处理方法一样
- java.lang.OutOfMemoryError: Metaspace
原因:当前线程无法从JVM申请元空间内存,JDK8之后原永久代中的类元数据迁移到元空间(堆 -> 直接内存),常量池继续在堆中
解决:
1)当定位到是元空间设置太小,修改配置
2)当定位到是内存泄露,则修改代码(通常在引用第三方包出现)
- java.lang.OutOfMemoryError: Direct buffer memory
原因:一般是工具为了做零拷贝,直接将数据存储在直接内存中,减少用户态和内核态内存拷贝,当未做内存回收时,空间不释放,抛出异常
解决:
1)定位到直接内存设置太小,修改配置
2)定位到内存泄露未释放内存,则修改异常代码
3)定位到Metaspace未设置大小,该空间内存泄露,则修改异常代码
疑难借助工具排查:
- VisualVM
- Eclipse MAT(Memory Analyzer Tool)
- Alibab Arthas

