一、堆栈信息自动保存:配置jvm参数
jvm启动参数中添加如下参数:用于OOM时自动保存堆栈信息;保存GC日志信息。
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp/heapdump.hprof
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/tmp/gc-%t.log
参数 | 描述 |
-XX:+HeapDumpOnOutOfMemoryError | JVM发生OOM时,生成heap dump文件 |
-XX:HeapDumpPath | heap dump文件的路径 |
-XX:+PrintGCDetails | 打印GC详细日志 |
-XX:+PrintGCDateStamps | GC日志中打印执行时间戳 |
-Xloggc | 把GC日志信息记录到文件。%t :为GC日志文件添加启动时间戳后缀,格式为:YYYY-MM-DD_HH-MM-SS |
完整jvm参数推荐配置:8G物理内存
6G~8G物理内存以上推荐使用 G1 垃圾回收器
-Xms4096m
-Xmx4096m
-XX:MetaspaceSize=512M
-XX:MaxDirectMemorySize=1024M
-Xss256k
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp/jvm/heapdump.hprof
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/tmp/jvm/gc-%t.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=100M
-Djava.net.preferIPv4Stack=true
-Duser.timezone=Asia/Shanghai
-Dfile.encoding=UTF-8
完整jvm参数推荐配置:4G物理内存
6G物理内存以下推荐使用默认垃圾回收器-XX:+UseParallelGC,即 Parallel Scavenge + Parallel Old
-Xms2048m
-Xmx2048m
-XX:MetaspaceSize=512M
-XX:MaxDirectMemorySize=1024M
-Xss128k
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp/jvm/heapdump.hprof
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/tmp/jvm/gc-%t.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=100M
-Djava.net.preferIPv4Stack=true
-Duser.timezone=Asia/Shanghai
-Dfile.encoding=UTF-8
二、堆栈信息手动保存
1. 栈信息手动保存:jstack
保存当前时刻的 线程栈 信息到 jstack.log 文件中(保存在当前路径下):
jstack PID号 > jstack.log
or
// -l : 附加锁信息,可用于分析死锁,但时间较长,慎用
jstack -l PID号 > jstack.log
2. 栈信息分析
统计java.lang.Thread.State出现的次数:
grep 'java.lang.Thread.State' jstack.log | wc -l
将线程栈文件的状态按次数排序显示:
grep -A 1 'java.lang.Thread.State' jstack.log | grep -v 'java.lang.Thread.State' | sort | uniq -c |sort -n
3. 堆信息手动保存:jmap
保存当前的 堆信息 到heapdump.hprof文件中:
// format=b:dump文件只支持二进制格式
jmap -dump:format=b,file=heapdump.hprof pid
or
// live:先Full GC,再dump存活对象
jmap -dump:format=b,live,file=heapdump.hprof pid
4. 堆信息分析
获取堆概要信息:
# 查看堆的概览信息,包括堆的各个参数的值,堆中新生代、年老代的内存大小、使用率等
jmap -heap PID
# 同样,如果 JVM 进程未响应命令,可以加上参数 -F 尝试,一般不需要
jmap -F -heap PID
获取堆中的类实例统计:
# 打印堆中的对象统计信息,以占用内存的大小排序。同样,如果 JVM 未响应命令,也可以使用 -F 参数
jmap -histo PID | head -50
or
# 只统计堆中的存活对象(先进行了一次Full GC),但使用 -F 时不支持 live
jmap -histo:live PID | more
5.查看GC信息:jstat
GC统计信息:
jstat -gc pid
// GC统计信息,可重点关注后5个参数:YGC、YGCT、FGC、FGCT、GCT
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
13312.0 13312.0 0.0 0.0 151040.0 1290.0 229376.0 15373.1 41728.0 38916.3 5632.0 5133.5 6 0.063 3 0.225 0.288
GC详细信息实时打印:
// 1000:打印间隔,单位毫秒
jstat -gcutil pid 1000
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 9.09 99.97 94.45 91.98 7428 282.820 175 1403.749 1686.568
三、堆栈信息分析工具
线程栈分析:GCeasy在线工具
官网地址:https://gceasy.io/
先使用命令: jstack -l PID号 > jstack.log 保存栈信息,然后将jstack.log保存到本地,最后上传到GCeasy进行分析,观察结果:
右边有下载PDF,可将分析结果保存到本地。
VisualVM
待定。。。
jvisualvm:jdk下启动VisualVM的命令工具。
MAT:Eclipse's Memory Analysis Tool独立版
独立版MAT下载:https://www.eclipse.org/mat/downloads.php
由于最新版本1.12.0所需的最低 Java 版本是 Java 11,所以下载旧版本:https://www.eclipse.org/mat/previousReleases.php
独立版MAT使用
左上角 File --> Open Heap Dump --> Leak Suspects Report(泄漏可疑报告)
Problem Suspect --> See stacktrace,可看到堆溢出时候的堆栈日志:
即可定位到出现问题的代码行!
Problem Suspect的详情页面:
Problem Suspect --> Details(Description、Shortest Paths To the Accumulation Point、Accumulated Objects in Dominator Tree等等)
Description(描述):
Shortest Paths To the Accumulation Point(从根元素到内存消耗聚集点的最短路径):
Accumulated Objects in Dominator Tree(内存消耗聚集对象信息):