前言
对于Java进程常见问题,可以通过JVM监控工具(比如Prometheus)、Arthas等,或者使用JDK自带的工具。如果第三方监控工具线上没有的话,对jdk自带的工具就要多熟悉熟悉。
线上Java进程运行常见问题:
- 内存溢出,OutOfMemoryError
- CPU使用率猛增
-
jmap用法
查看java进程内存占用情况。通过这个命令,可以看出哪些对象最消耗内存。输出结果最后有
Total统计结果。jmap -histo pid
查看堆内存占用情况
jmap -heap pid
导出dump内存溢出的文件,并导入到jvisualvm客户端进行查看。
jmap -dump:file=a.dump pid# 或者设置JVM参数:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./a.dump
使用jstack排查java进程占用CPU使用率猛增问题
使用top查看java进程的pid
top -p pid
在top界面按
H,获取占用CPU最高的线程ID,将线程ID转16进制。- 使用jstack查看该线程ID堆栈信息
# 假设进程ID为7147,线程ID的十进制为7163,十六进制为1bfbjstack 7147 | grep -A 10 -B 10 1bfb
jstat用法
垃圾回收统计
jstat -gc pid# S0C: 第一个survivor区的容量# S1C: 第二个survivor区的容量# S0U: 第一个survivor区已使用的容量# S1U: 第二个survivor区已使用的容量# EC: Eden区的容量# EU: Eden区的使用量# OC: Old区的容量# OU: Old区的使用量# MC: Metaspace的容量# MU: Metaspace的使用量# CCSC: 压缩指针的容量# CCSU: 压缩指针的使用量# YGC: YoungGC的次数# YGCT: 本次YoungGC耗时# FGC: Full GC的次数# FGCT: 本次Full GC耗时# GCT: 总的GC耗时
连续观察gc情况
# 每隔1000ms打印一次,总共打印10次jstat -gc pid 1000 10
堆内存情况
jstat -gccapacity pid# NGCMN: 新生代最小容量# NGCMX: 新生代最大容量# NGC: 当前新生代容量# S0C: 第一个Survivor区大小# S1C: 第二个Survivor区大小# EC: Eden区的大小# OGCMN: 老年代最小容量# OGCMX: 老年代最大容量# OGC: 当前老年代大小# OC: 当前老年区大小# MCMN: 最小元数据容量# MCMX: 最大元数据容量# MC: 当前元数据空间大小# CCSMN: 最小压缩类空间大小# CCSMX: 最大压缩类空间大小# CCSC: 当前压缩类空间大小# YGC: 年轻代gc次数# FGC: 老年代GC次数
新生代gc统计
jstat -gcnew pid
新生代堆内存情况
jstat -gcnewcapacity pid
老年代gc统计
jstat -gcold pid
老年代堆内存情况
jstat -gcoldcapacity pid
元空间堆内存情况
jstat -gcmetacapacity pid
整体情况
jstat -gcutil pid# S0: Survivor 1区的使用比例# E: Eden区使用比例# ...
使用jinfo查看jvm参数
# 包含flags和sysprops的信息jinfo pid# 只有自定义的jvm参数jinfo -flags pid# 只有系统参数jinfo -sysprops pid
参考资料
man jmapman jstackman jstatman jinfo
