OOM排查思路
OOM排查思路一、是内存溢出Or内存泄漏?内存溢出内存泄漏二、工具的使用VisualVMJmapGC日志JVM参数三、排查过程
一、是内存溢出Or内存泄漏?
内存溢出
内存本身就太小,满足不了程序运行最小内存,则是内存溢出。
解决思路:直接加大内存。
内存泄漏
观察内存,每一次gc后都有某一些不要的对象是gc不了的,一直占着空间,导致越来越多的对象堆积在内存中得不到释放,最终内存泄漏导致内存溢出。
解决思路:应该从代码层面进行解决,不需要的对象不要建立强引用。
二、工具的使用
VisualVM
该软件可以看到jvm进程实时的cpu、堆、calssess、线程占用情况的变化
对于某一个时刻,也支持dump出文件进行分析
一定要安装Visual GC插件,可以实时看到堆内存各个区域的变化
Jmap
Jmap是jdk自带的命令,支持对堆内存进行查看统计操作
例如:jmap -heap [pid]
可以看到每个区一共多少大,用了多少,还剩下多少
GC日志
#GC后堆内存状态
Heap after GC invocations=452 (full 18):
def new generation total 223104K, used 8553K [0x00000000c6200000, 0x00000000d5410000, 0x00000000d96a0000)
eden space 198336K, 0% used [0x00000000c6200000, 0x00000000c6200000, 0x00000000d23b0000)
from space 24768K, 34% used [0x00000000d3be0000, 0x00000000d443a670, 0x00000000d5410000)
to space 24768K, 0% used [0x00000000d23b0000, 0x00000000d23b0000, 0x00000000d3be0000)
tenured generation total 495616K, used 244951K [0x00000000d96a0000, 0x00000000f7aa0000, 0x0000000100000000)
the space 495616K, 49% used [0x00000000d96a0000, 0x00000000e85d5e00, 0x00000000e85d5e00, 0x00000000f7aa0000)
Metaspace used 121936K, capacity 129174K, committed 132224K, reserved 1163264K
class space used 15581K, capacity 17393K, committed 18304K, reserved 1048576K
}
#GC前堆内存状态
{Heap before GC invocations=452 (full 18):
def new generation total 223104K, used 206889K [0x00000000c6200000, 0x00000000d5410000, 0x00000000d96a0000)
eden space 198336K, 100% used [0x00000000c6200000, 0x00000000d23b0000, 0x00000000d23b0000)
from space 24768K, 34% used [0x00000000d3be0000, 0x00000000d443a670, 0x00000000d5410000)
to space 24768K, 0% used [0x00000000d23b0000, 0x00000000d23b0000, 0x00000000d3be0000)
tenured generation total 495616K, used 244951K [0x00000000d96a0000, 0x00000000f7aa0000, 0x0000000100000000)
the space 495616K, 49% used [0x00000000d96a0000, 0x00000000e85d5e00, 0x00000000e85d5e00, 0x00000000f7aa0000)
Metaspace used 121983K, capacity 129174K, committed 132224K, reserved 1163264K
class space used 15582K, capacity 17393K, committed 18304K, reserved 1048576K
#GC时间、[空间GC前后大小]、GC使用时间
2021-09-24T15:32:35.319+0800: 3055.215: [GC (Allocation Failure) 2021-09-24T15:32:35.319+0800: 3055.215: [DefNew: 206889K->8627K(223104K), 0.0290467 secs] 451841K->253578K(718720K), 0.0291708 secs] [Times: user=0.02 sys=0.01, real=0.03 secs]
JVM参数
-XX:+HeapDumpOnOutOfMemoryError
:出现oom时将堆dump下来
-XX:HeapDumpPath=/app/heapdump.hprof
:dump文件存放位置
-Dcom.sun.management.jmxremote.authenticate=false
:远程连接校验
-Dcom.sun.management.jmxremote.ssl=false
:远程连接ssl方式
-Dcom.sun.management.jmxremote.port=33306
:远程连接端口
-XX:NewRatio
:年轻代和老年代大小比例,默认是2,即1:2
-XX:MaxTenuringThreshold
:年轻代经过N次gc后还存活会进入老年代
三、排查过程
-
先确定是内存泄漏还是内存溢出
- 由于项目执行任务时开始都是可以执行的,且并发执行多个任务都没有问题,而当任务执行多几次后,就会出现OOM
- 观察每次GC后的堆内存空间,可以看到随着任务执行次数越来越多,GC执行后新生代能够清空,而老年代GC后的数据还是比较满的,则可以判定由于某些数据GC不掉,且该部分数据越来越多导致内存不足出现内存泄漏
-
在一次full GC后dump出堆内存文件,查看占用大内存的对象的GCRoot,可以看到被一个static引用着,因此得不到释放。
-
最终可以确定是因为程序运行过程中一直往该static Map添加元素,而用完了不去清理掉,导致对象被该Map强引用,不会被GC掉,造成内存泄漏。
\