最近排查了生产环境服务假死的问题,CPU 被占满,Java 中的线程都在执行 Full GC,为了 dump JVM 线程栈信息与堆内存信息,查了很多指令。下面做一个常用指令的简单汇总:
查看 Java 进程
jps
jrockit dump 操作
jrcmd <pid> hprofdump filename=/test.hprof
jstack dump 线程栈信息
jstack <pid> > test.dump
参数:
jstack [-l] <pid>: 连接到一个运行中的进程
jstack -F [-m] [-l] <pid>: 连接到一个挂起的进程
jstack [-m] [-l] <executable> <core>: 连接到核心文件
jstack [-m] [-l] [server_id@]<remote server IP or hostname>: 连接到远程调试服务
jmap dump 堆内存
jmap [option] <pid>: 连接到正在运行的进程
jmap [option] <executable <core>: 连接到核心文件
jmap [option] [server_id@]<remote server IP or hostname>: 连接到远程调试服务
option:
无参数: 类似 Solaris pmap,查看虚拟机内存使用情况
jmap 8888
-heap: 打印 heap 的概要信息,GC 使用的算法,heap 的配置及 JVM 堆内存的使用情况
jmap -heap 8888
-histo[:live]: 打印 Java 堆对象的直方统计信息,live 参数加上只统计活的对象
jmap -histo:live 8888
-clstats: 打印类加载器的统计情况
jmap -clstats 8888
-finalizerinfo: 打印正等候回收的对象的信息
jmap -clstats 8888
-dump:<dump-options>: 使用 hprof 二进制形式,输出 jvm 的 heap 到文件,live 子选项可选只输出活的对象到文件
jmap -dump:live,format=b,file=heap.bin 8888
-F: 强制 dump,-dump 和 -histo 的 live 子参数无效
jmap -heap -F 8888
-J<flag>: 传递参数到 JVM 运行系统
jmap -J-Xmx512m 8888
获取堆信息的 3 种方式
jmap -dump:live,format=b,file=heap.bin 8888
kill -3 <pid>
增加 JVM 启动参数
-XX:+HeapDumpBeforeFullGC
-XX:HeapDumpPath=/dump
找到占用 CPU 过高的线程,分析
top
定位到占用 CPU 高的进程 PID
top -H -p <pid> 或者 ps -mp <pid> -o THREAD,tid,time | sort -rn
查看对应进程的哪个线程占用 CPU 过高
printf "%x\n" tid
将需要的线程 ID 转换为 16 进制
jstack pid > pid.txt
jstack pid |grep tid -A 30
导出 CPU 占用较高的进程的线程栈,用 16 进制 tid 在 pid.txt 查找;或打印线程的栈信息
jhat,分析 java 的堆,并启动一个 web server,可以将堆中对象的数量,大小等信息以 html 的形式显示出来,并支持对象查询语言。因占有大量内存,一般不在服务器上执行使用
jhat -J-Xmx512m <heap dump file>
http://ip:7000/,查看 html
执行对象查询语句 Object Query Language:select s from java.lang.String s where s.count > 100
jstat,查看堆内存各部分的使用量、垃圾回收、类编译、加载的情况
jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]
类加载统计:jstat -class 8888
参数说明:
Loaded:加载class的数量
Bytes:所占用空间大小
Unloaded:未加载数量
Bytes:未加载占用空间
Time:时间
编译统计:jstat -compiler 8888
参数说明:
Compiled:编译数量
Failed:失败数量
Invalid:不可用数量
Time:时间
FailedType:失败类型
FailedMethod:失败的方法
垃圾回收统计:jstat -gc 8888
参数说明:
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
堆内存统计:jstat -gccapacity 8888
参数说明:
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0C:第一个幸存区大小
S1C:第二个幸存区的大小
EC:伊甸园区的大小
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:当前老年代大小
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代gc次数
FGC:老年代GC次数
新生代垃圾回收统计:jstat -gcnew 8888
参数说明:
S0C:第一个幸存区大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
TT:对象在新生代存活的次数
MTT:对象在新生代存活的最大次数
DSS:期望的幸存区大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
新生代内存统计:jstat -gcnewcapacity 8888
参数说明:
NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0CMX:最大幸存1区大小
S0C:当前幸存1区大小
S1CMX:最大幸存2区大小
S1C:当前幸存2区大小
ECMX:最大伊甸园区大小
EC:当前伊甸园区大小
YGC:年轻代垃圾回收次数
FGC:老年代回收次数
老年代垃圾回收统计:jstat -gcold 8888
参数说明:
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
OC:老年代大小
OU:老年代使用大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
老年代内存统计:jstat -gcoldcapacity 8888
参数说明:
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:老年代大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
JDK1.7 永久代空间统计:jstat -gcpermcapacity 8888
参数说明:
PGCMN:最小永久代容量
PGCMX:最大永久代容量
PGC:当前新生成的永久代空间大小
PC :永久代空间大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
JDK1.8 元数据空间统计:jstat -gcmetacapacity 8888
参数说明:
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
垃圾回收统计:jstat -gcutil 8888
参数说明:
S0:幸存1区当前使用比例
S1:幸存2区当前使用比例
E:伊甸园区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩使用比例
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
JVM编译方法统计:jstat -printcompilation 8888
参数说明:
Compiled:最近编译方法的数量
Size:最近编译方法的字节码数量
Type:最近编译方法的编译类型