前言
对于Java进程常见问题,可以通过JVM监控工具(比如Prometheus)、Arthas等,或者使用JDK自带的工具。如果第三方监控工具线上没有的话,对jdk自带的工具就要多熟悉熟悉。
线上Java进程运行常见问题:
- 内存溢出,OutOfMemoryError
- CPU使用率猛增
- JVM参数调优
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,十六进制为1bfb jstack 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
参考资料
- JVM调优工具锦囊
man jmap
man jstack
man jstat
man jinfo