常用的JDK检测命令

发表时间:2017-10-31 10:58:41 浏览量( 22 ) 留言数( 0 )

学习目标:

1、了解常用的JDK相关命令


学习过程:

一、jps命令     

    jps主要用来输出JVM中运行的进程状态信息。一般我们可以使用这个命令查看进程号和进程是否还在启动。语法格式如下:

jps [options] [hostid]

    如果不指定hostid就默认为当前主机或服务器。

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

-q 不输出类名、Jar名和传入main方法的参数

-m 输出传入main方法的参数

-l 输出main类或Jar的全限名

-v 输出传入JVM的参数

   比如下面:

 jps -m -l

10464 com.minstone.oa.workflow.FlowProviderApplication

2156 org.apache.zookeeper.server.quorum.QuorumPeerMain D:\program\zookeeper-3.3.6\bin\..\conf\zoo.cfg



二、 jstack

    jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下:

jstack [option] pid

jstack [option] executable core

jstack [option] [server-id@]remote-hostname-or-ip

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

-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况

-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)

    jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。

    第一步先找出Java进程ID,我部署在服务器上的Java应用名称为mrf-center:

root@ubuntu:/# ps -ef | grep mrf-center | grep -v grep

root     21711     1  1 14:47 pts/3    00:02:10 java -jar mrf-center.jar

    得到进程ID为21711,第二步找出该进程内最耗费CPU的线程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我这里用第三个,输出如下:

attcontent/570fb0f5-5745-473a-8ba6-52d7000a7903.png


printf "%x\n" 21742

得到21742的十六进制值为54ee,下面会用到。    

OK,下一步终于轮到jstack上场了,它用来输出进程21711的堆栈信息,然后根据线程ID的十六进制值grep,如下:

 jstack 21711 | grep 54ee

"PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait() [0x00007f94c6eda000]

    可以看到CPU消耗在PollIntervalRetrySchedulerThread这个类的Object.wait(),



三、jmap(Memory Map)和jhat(Java Heap Analysis Tool)

    jmap用来查看堆内存使用状况,一般结合jhat使用。

    jmap语法格式如下:

jmap [option] pid

jmap [option] executable core

jmap [option] [server-id@]remote-hostname-or-ip

    如果运行在64位JVM上,可能需要指定-J-d64命令选项参数。

jmap -permstat pid

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

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

    使用jmap -histo[:live] pid查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象

    还有一个很常用的情况是:用jmap把进程内存使用情况dump到文件中,再用jhat分析查看。jmap进行dump命令格式如下:

    jmap -dump:format=b,file=dumpFileName pid

    我一样地对上面进程ID为21711进行Dump:


jmap -dump:format=b,file=/tmp/dump.dat 21711     

Dumping heap to /tmp/dump.dat ...

Heap dump file created

   dump出来的文件可以用MAT、VisualVM等工具查看,这里用jhat查看:

 jhat -port 9998 /tmp/dump.dat

Reading from /tmp/dump.dat...

Dump file created Tue Jan 28 17:46:14 CST 2014

Snapshot read, resolving...

Resolving 132207 objects...

Chasing references, expect 26 dots..........................

Eliminating duplicate references..........................

Snapshot resolved.

Started HTTP server on port 9998

Server is ready.

     注意如果Dump文件太大,可能需要加上-J-Xmx512m这种参数指定最大堆内存,即jhat -J-Xmx512m -port 9998 /tmp/dump.dat。然后就可以在浏览器中输入主机地址:9998查看了:


attcontent/79efda48-4df1-46e4-9150-eecab240cdee.png


四、jstat

    jstat是JDK自带的一个轻量级小工具。全称“Java Virtual Machine statistics monitoring tool”,它位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。

jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。参考格式如下:

jstat -options 

可以列出当前JVM版本支持的选项,常见的有

  class (类加载器) 

  compiler (JIT) 

  gc (GC堆状态) 

  gccapacity (各区大小) 

  gccause (最近一次GC统计和原因) 

  gcnew (新区统计)

  gcnewcapacity (新区大小)

  gcold (老区统计)

  gcoldcapacity (老区大小)

  gcpermcapacity (永久区大小)

  gcutil (GC统计汇总)

  printcompilation (HotSpot编译统计)

1、jstat –class<pid> : 显示加载class的数量,及所占空间等信息。

具体描述

Loaded 装载的类的数量

Bytes 装载类所占用的字节数

Unloaded 卸载类的数量

Bytes 卸载类的字节数

Time 装载和卸载类所花费的时间

2、jstat -compiler <pid>显示VM实时编译的数量等信息。

具体描述

Compiled 编译任务执行数量 

Failed 编译任务执行失败数量 

Invalid   编译任务执行失效数量 

Time   编译任务消耗时间

FailedType 最后一个编译失败任务的类型

FailedMethod 最后一个编译失败任务所在的类及方法

3、jstat -gc <pid>: 可以显示gc的信息,查看gc的次数,及时间。


具体描述

S0C    年轻代中第一个survivor(幸存区)的容量 (字节)

S1C   年轻代中第二个survivor(幸存区)的容量 (字节)

S0U   年轻代中第一个survivor(幸存区)目前已使用空间 (字节)

S1U     年轻代中第二个survivor(幸存区)目前已使用空间 (字节)

EC      年轻代中Eden(伊甸园)的容量 (字节)

EU       年轻代中Eden(伊甸园)目前已使用空间 (字节)

OC        Old代的容量 (字节)

OU      Old代目前已使用空间 (字节)

PC    Perm(持久代)的容量 (字节)

PUPerm(持久代)目前已使用空间 (字节)

YGC    从应用程序启动到采样时年轻代中gc次数

YGCT   从应用程序启动到采样时年轻代中gc所用时间(s)

FGC   从应用程序启动到采样时old代(全gc)gc次数

FGCT    从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT    从应用程序启动到采样时gc用的总时间(s)

4、jstat -gccapacity <pid>:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小

具体描述

NGCMN   年轻代(young)中初始化(最小)的大小(字节)

NGCMX    年轻代(young)的最大容量 (字节)

NGC    年轻代(young)中当前的容量 (字节)

S0C  年轻代中第一个survivor(幸存区)的容量 (字节)

S1C      年轻代中第二个survivor(幸存区)的容量 (字节)

EC     年轻代中Eden(伊甸园)的容量 (字节)

OGCMN     old代中初始化(最小)的大小 (字节)

OGCMX      old代的最大容量(字节)

OGCold代当前新生成的容量 (字节)

OC     Old代的容量 (字节)

PGCMN   perm代中初始化(最小)的大小 (字节)

PGCMX    perm代的最大容量 (字节)  

PGC      perm代当前新生成的容量 (字节)

PC    Perm(持久代)的容量 (字节)

YGC   从应用程序启动到采样时年轻代中gc次数

FGC   从应用程序启动到采样时old代(全gc)gc次数

5、jstat -gcutil <pid>:统计gc信息

显示列名

具体描述

S0    年轻代中第一个survivor(幸存区)已使用的占当前容量百分比

S1    年轻代中第二个survivor(幸存区)已使用的占当前容量百分比

E     年轻代中Eden(伊甸园)已使用的占当前容量百分比

O     old代已使用的占当前容量百分比

P    perm代已使用的占当前容量百分比

YGC    从应用程序启动到采样时年轻代中gc次数

YGCT   从应用程序启动到采样时年轻代中gc所用时间(s)

FGC   从应用程序启动到采样时old代(全gc)gc次数

FGCT    从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT    从应用程序启动到采样时gc用的总时间(s)

6、jstat -gcnew <pid>:年轻代对象的信息。

具体描述

S0C   年轻代中第一个survivor(幸存区)的容量 (字节)

S1C   年轻代中第二个survivor(幸存区)的容量 (字节)

S0U   年轻代中第一个survivor(幸存区)目前已使用空间 (字节)

S1U  年轻代中第二个survivor(幸存区)目前已使用空间 (字节)

TT   持有次数限制

MTT  最大持有次数限制

EC   年轻代中Eden(伊甸园)的容量 (字节)

EU    年轻代中Eden(伊甸园)目前已使用空间 (字节)

YGC    从应用程序启动到采样时年轻代中gc次数

YGCT    从应用程序启动到采样时年轻代中gc所用时间(s)

7、jstat -gcnewcapacity<pid>: 年轻代对象的信息及其占用量。

具体描述

NGCMN     年轻代(young)中初始化(最小)的大小(字节)

NGCMX      年轻代(young)的最大容量 (字节)

NGC     年轻代(young)中当前的容量 (字节)

S0CMX    年轻代中第一个survivor(幸存区)的最大容量 (字节)

S0C    年轻代中第一个survivor(幸存区)的容量 (字节)

S1CMX    年轻代中第二个survivor(幸存区)的最大容量 (字节)

S1C      年轻代中第二个survivor(幸存区)的容量 (字节)

ECMX  年轻代中Eden(伊甸园)的最大容量 (字节)

EC     年轻代中Eden(伊甸园)的容量 (字节)

YGC  从应用程序启动到采样时年轻代中gc次数

FGC  从应用程序启动到采样时old代(全gc)gc次数

8、jstat -gcold <pid>:old代对象的信息。

具体描述

PC      Perm(持久代)的容量 (字节)

PU       Perm(持久代)目前已使用空间 (字节)

OC         Old代的容量 (字节)

OU      Old代目前已使用空间 (字节)

YGC   从应用程序启动到采样时年轻代中gc次数

FGC   从应用程序启动到采样时old代(全gc)gc次数

FGCT    从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT  从应用程序启动到采样时gc用的总时间(s)

9、stat -gcoldcapacity <pid>: old代对象的信息及其占用量。

具体描述

OGCMN      old代中初始化(最小)的大小 (字节)

OGCMX       old代的最大容量(字节)

OGC        old代当前新生成的容量 (字节)

OC      Old代的容量 (字节)

YGC  从应用程序启动到采样时年轻代中gc次数

FGC   从应用程序启动到采样时old代(全gc)gc次数

FGCT    从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT从应用程序启动到采样时gc用的总时间(s)

 

10、jstat -gcpermcapacity<pid>: perm对象的信息及其占用量。

具体描述

PGCMN     perm代中初始化(最小)的大小 (字节)

PGCMX      perm代的最大容量 (字节)  

PGC        perm代当前新生成的容量 (字节)

PC     Perm(持久代)的容量 (字节)

YGC  从应用程序启动到采样时年轻代中gc次数

FGC   从应用程序启动到采样时old代(全gc)gc次数

FGCT  从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT 从应用程序启动到采样时gc用的总时间(s)

 

11、jstat -printcompilation <pid>:当前VM执行的信息。

具体描述 Compiled 

编译任务的数目 Size 

方法生成的字节码的大小 Type

编译类型 Method

类名和方法名用来标识编译的方法。类名使用/做为一个命名空间分隔符。方法名是给定类中的方法。上述格式是由-XX:+PrintComplation选项进行设置的

 


五、示例

for PID in $PIDS ; do

jstack $PID > $DATE_DIR/jstack-$PID.dump 2>&1

echo -e ".\c"

jinfo $PID > $DATE_DIR/jinfo-$PID.dump 2>&1

echo -e ".\c"

jstat -gcutil $PID > $DATE_DIR/jstat-gcutil-$PID.dump 2>&1

echo -e ".\c"

jstat -gccapacity $PID > $DATE_DIR/jstat-gccapacity-$PID.dump 2>&1

echo -e ".\c"

jmap $PID > $DATE_DIR/jmap-$PID.dump 2>&1

echo -e ".\c"

jmap -heap $PID > $DATE_DIR/jmap-heap-$PID.dump 2>&1

echo -e ".\c"

jmap -histo $PID > $DATE_DIR/jmap-histo-$PID.dump 2>&1

echo -e ".\c"

if [ -r /usr/sbin/lsof ]; then

/usr/sbin/lsof -p $PID > $DATE_DIR/lsof-$PID.dump

echo -e ".\c"

fi

done