本文介绍JVM的常用工具

jstack

主要用来做线程堆栈分析,常用来分析CPU和load高的问题,一般步骤如下:

  1. 找到java进程的pid ps -ef | grep java
  2. 找到Java进程中的占用cpu较高的线程的线程id top –Hp pid
  3. java进程的信息dump到本地文件中 命令:jstack -l -m pid > dump.txt

jstack线程信息dump内容的线程ID是十六进制,top命令获取查询到的线程id是十进制,需要做一次转换,可以直接使用命令printf "%0x\n" thread_id来转。

命令行参数选项说明如下:

-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)

dump文件里,值得关注的线程状态有:

死锁,Deadlock(重点关注)
执行中,Runnable
等待资源,Waiting on condition(重点关注)
等待获取监视器,Waiting on monitor entry(重点关注)
暂停,Suspended
对象等待中,Object.wait() 或 TIMED_WAITING
阻塞,Blocked(重点关注)
停止,Parked

jmap

jmap用来查看堆内存使用状况

内存堆栈

jmap -heap pid

查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况。

类加载器信息

jmap -permstat pid

打印进程的类加载器和类加载器加载的持久代对象信息,输出:类加载器名称、对象是否存活(不可靠)、对象地址、父类加载器、已加载的类大小等信息

内存对象统计

jmap -histo:live pid

查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象

dump信息分析

jmap -dump:file=/home/admin/jvm.log,live

把进程内存使用情况dump到文件中,可以使用MAT工具来分析

jstat

jstat用于展现jvm的性能统计数据

jstat -gc pid

比如:

root@centos7:/# jstat -gc 21711  
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT   
192.0  192.0          6144.0   1854.9   32000.0     4111.6   55296.0 25472.7        0.431         0.218    0.649
192.0  192.0          6144.0   1972.2   32000.0     4111.6   55296.0 25472.7        0.431         0.218    0.649

先看JVM堆内存布局

堆内存 = 年轻代 + 年老代 + 永久代
年轻代 = Eden区 + 两个Survivor区(和To)
解释各列含义:
S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used)
EC、EU:Eden区容量和使用量
OC、OU:年老代容量和使用量
PC、PU:永久代容量和使用量
YGC、YGT:年轻代GC次数和GC耗时
FGC、FGCT:Full GC次数和Full GC耗时
GCT:GC总耗时

参考