目录
- 1. 日志分析
- 2. MAT 工具
- 2.1 日志打印方式
- 2.1.1 HeapDumpOnOutOfMemoryError(推荐)
- 2.1.2 jmp 命令
- 2.2 MAT分析方式
- 2.2.1 饼图分析
- 2.2.2 树形图分析
- 2.2.2 泄漏疑点
- 3. 优化
首先说一下结论:通过MAT工具分析才是最精准的,直接通过日志排查可能不是主要原因。
1. 日志分析
直接从日志文件定位 (不精准)
可以看到这是个 OutOfMemoryError
内存溢出异常,Java heap space
表示java堆内存溢出。并且 at org.example.controller.Test.test(Test.java:27)
指定了具体位置,找到具体代码就能定位问题。
上面的方法不一定是精准的,有可能其他地方占用了百分之80内存,刚好一个低内存方法创建对象的时候OOM,所以这种方式存在误判性。
2. MAT 工具
2.1 日志打印方式
通过打印dump文件通过MAT工具查看。
打印dump文件方式有两种,一种是在启动jar包添加 -XX:+HeapDumpOnOutOfMemoryError
(推荐),一种是执行 jmp -dump
命令
2.1.1 HeapDumpOnOutOfMemoryError(推荐)
在启动jar包时,添加-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof
,在服务OOM时会打印dump文件到当前目录heapdump.hprof文件中,然后通过MAT工具查看
例如:通过
nohup java -Xms512m -Xmx512m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof -jar byzq-yc.jar > ./byzq-yc.log 2>&1 &
启动服务。
将 heapdump.hprof文件拷贝出来,打开MAT工具,选择File -> Open File -> 选择 heapdump.hprof
加载完后,点击 Finish
2.1.2 jmp 命令
首先使用 jps
查看进程ID,或者top
查看内存较高进程ID,然后使用jmap来生成堆转储文件:
jmap -dump:live,format=b,file=heapdump.dat<PID>
后续跟前面一样,通过mat工具分析即可
2.2 MAT分析方式
2.2.1 饼图分析
直接根据饼图分析,占用最大的这部分多半就是引起OOM的元凶,实际可能会存在多个占用比例比较大的,逐个分析就好
通过 Java Basics -> Thread Details 或 Thread Overview and Stacks 都可以找到对应的代码位置
2.2.2 树形图分析
点击 Dominator Tree 我们能看到线程树形的内存占比
可以看到这个Object 占比比较高,同样通过 Java Basics -> Thread Details 或 Thread Overview and Stacks 都可以找到对应的代码位置
2.2.2 泄漏疑点
点击 Leak Suspects 可以直接查看到一个报错信息
点击Details
不仅可以查看到一个内存占比,还能查看到报错信息
3. 优化
分析具体原因后,考虑是代码原因则优化代码。如果代码问题不大则考虑提升堆内存空间