JDK常用分析工具

在JDK的bin目录下有很多命令行工具

[root@iZ2ze1224b1em0jij7qlssZ bin]#  ls -lak|grep j
-rwxr-xr-x 1 root root   7 Apr 18  2019 idlj
-rwxr-xr-x 1 root root   7 Apr 18  2019 jar
-rwxr-xr-x 1 root root   7 Apr 18  2019 jarsigner
-rwxr-xr-x 1 root root   7 Apr 18  2019 java
-rwxr-xr-x 1 root root   7 Apr 18  2019 javac
-rwxr-xr-x 1 root root   7 Apr 18  2019 javadoc
-rwxr-xr-x 1 root root   7 Apr 18  2019 javah
-rwxr-xr-x 1 root root   7 Apr 18  2019 javap
-rwxr-xr-x 1 root root   3 Apr 18  2019 java-rmi.cgi
-rwxr-xr-x 1 root root   7 Apr 18  2019 jcmd
-rwxr-xr-x 1 root root   7 Apr 18  2019 jconsole
-rwxr-xr-x 1 root root   7 Apr 18  2019 jdb
-rwxr-xr-x 1 root root   7 Apr 18  2019 jdeps
-rwxr-xr-x 1 root root   7 Apr 18  2019 jhat
-rwxr-xr-x 1 root root   7 Apr 18  2019 jinfo
-rwxr-xr-x 1 root root   7 Apr 18  2019 jjs
-rwxr-xr-x 1 root root   7 Apr 18  2019 jmap
-rwxr-xr-x 1 root root   7 Apr 18  2019 jps
-rwxr-xr-x 1 root root   7 Apr 18  2019 jrunscript
-rwxr-xr-x 1 root root   7 Apr 18  2019 jsadebugd
-rwxr-xr-x 1 root root   7 Apr 18  2019 jstack
-rwxr-xr-x 1 root root   7 Apr 18  2019 jstat
-rwxr-xr-x 1 root root   7 Apr 18  2019 jstatd
-rwxr-xr-x 1 root root   7 Apr 18  2019 xjc

可以看到各个工具的大小基本上都稳定在7k左右,这个不是JDK开发团队刻意为之的,而是因为这些工具大多数是jdklib ools.jar类库的一层薄包装而已,他们的主要功能代码是在tools类库中实现的。命令行工具的好处是:当应用程序部署到生产环境后,无论是直接接触物理服务器还是远程telnet到服务器上都会受到限制。而借助tools.jar类库里面的接口,我们可以直接在应用程序中实现功能强大的监控分析功能。

这里主要介绍如下几个工具:

  1、jps:查看本机java进程信息

  2、jstack:打印线程的信息,制作 线程dump文件

  3、jmap:打印内存映射信息,制作 堆dump文件

  4、jstat:性能监控工具

  5、jhat:内存分析工具,用于解析堆dump文件并以适合人阅读的方式展示出来

  6、jconsole:简易的JVM可视化工具

  7、jvisualvm:功能更强大的JVM可视化工具

JAVA Dump:

JAVA Dump就是虚拟机运行时的快照,将虚拟机运行时的状态和信息保存到文件中,包括:

线程dump:包含所有线程的运行状态,纯文本格式

堆dump:包含所有堆对象的状态,二进制格式

1、jps

显示当前所有java进程pid的命令,我们可以通过这个命令来查看到底启动了几个java进程(因为每一个java程序都会独占一个java虚拟机实例),不过jps有个缺点是只能显示当前用户的进程id,要显示其他用户的还只能用linux的ps命令。

[root@iZ2ze1224b1em0jij7qlssZ bin]# jps
25699 jar
10947 jar
26949 QuorumPeerMain
25350 jar
22696 jar
21993 jar
7337 jar
3241 jar
5130 jar
10220 jar

 执行jps命令,会列出所有正在运行的java进程,其中jps命令也是一个java程序。前面的数字就是进程的id。

jps -help:

[root@iZ2ze1224b1em0jij7qlssZ bin]# jps -help
usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

Definitions:
    <hostid>:      <hostname>[:<port>]

jps -l :输出应用程序main.class的完整package名或者应用程序jar文件完整路径名。

[root@iZ2ze1224b1em0jij7qlssZ bin]# jps -l10220 inner-0.0.1-SNAPSHOT.jar
2860 org.apache.catalina.startup.Bootstrap2897 org.apache.catalina.startup.Bootstrap2774 org.apache.catalina.startup.Bootstrap
26488 org.apache.catalina.startup.Bootstrap16764 sun.tools.jps.Jps
7965 org.apache.catalina.startup.Bootstrap
2078 maintenancekey-server.jar

jps -v 输出传递给JVM的参数

[root@iZ2ze1224b1em0jij7qlssZ bin]# jps -v
25699 jar
10947 jar
26949 QuorumPeerMain -Dzookeeper.log.dir=. -Dzookeeper.root.logger=INFO,CONSOLE -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false
25350 jar
22696 jar
21993 jar
7337 jar
3241 jar
5130 jar
10220 jar

jps失效

我们在定位问题过程会遇到这样一种情况,用jps查看不到进程id,用ps -ef | grep java却能看到启动的java进程。

要解释这种现象,先来了解下jps的实现机制:

java程序启动后,会在目录/tmp/hsperfdata_{userName}/下生成几个文件,文件名就是java进程的pid,因此jps列出进程id就是把这个目录下的文件名列一下而已,至于系统参数,则是读取文件中的内容。

我们来思考下:如果由于磁盘满了,无法创建这些文件,或者用户对这些文件没有读的权限。又或者因为某种原因这些文件或者目录被清除,出现以上这些情况,就会导致jps命令失效。

如果jps命令失效,而我们又要获取pid,还可以使用以下两种方法:

1、top | grep java
2、ps -ef |grep java

2、jstack

用于生成指定进程当前时刻的线程快照,线程快照是当前java虚拟机每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致长时间等待。

[root@iZ2ze1224b1em0jij7qlssZ bin]# jstack 2078
2021-07-14 13:33:27
Full thread dump OpenJDK 64-Bit Server VM (25.212-b04 mixed mode):

"Attach Listener" #526 daemon prio=9 os_prio=0 tid=0x00007f07b000b000 nid=0x4a63 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"http-nio-8501-exec-79" #382 daemon prio=5 os_prio=0 tid=0x00007f079004f000 nid=0x279d waiting on condition [0x00007f078f9fc000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000006c6100118> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

3、jmap

用于打印指定java进程的共享对象内存映射或堆内存细节。

堆Dump是反映堆使用情况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等。一般在内存不足,GC异常等情况下,我们会去怀疑内存泄漏,这个时候就会去打印堆Dump。

[root@iZ2ze1224b1em0jij7qlssZ bin]# jmap -h
Usage:
    jmap [option] <pid>
        (to connect to running process)
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system

1)、jmap pid

[root@iZ2ze1224b1em0jij7qlssZ bin]# jmap 25699 
Attaching to process ID 25699, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.212-b04
0x0000000000400000      6K      /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/bin/java
0x00007fd39d4bb000      108K    /lib64/libresolv-2.12.so
0x00007fd39d6d5000      27K     /lib64/libnss_dns-2.12.so
0x00007fd3e6237000      466K    /lib64/libfreeblpriv3.so
0x00007fd3e64b0000      242K    /lib64/libnspr4.so
0x00007fd3e66ef000      18K     /lib64/libplc4.so
0x00007fd3e68f4000      14K     /lib64/libplds4.so
0x00007fd3e6af8000      187K    /usr/lib64/libnssutil3.so
0x00007fd3e6d27000      1305K   /usr/lib64/libnss3.so
0x00007fd3e706f000      181K    /usr/lib64/libsmime3.so
0x00007fd3e729c000      328K    /usr/lib64/libssl3.so
0x00007fd3e74ef000      46K     /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64/libsunec.so
0x00007fd3ec63c000      71K     /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64/libnio.so
0x00007fd3ec84e000      38K     /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64/libmanagement.so
0x00007fd3ecd58000      94K     /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64/libnet.so
0x00007fd3ff7ad000      34K     /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64/libzip.so
0x00007fd3ff9b6000      64K     /lib64/libnss_files-2.12.so
0x00007fd3ffbc4000      175K    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64/libjava.so
0x00007fd3ffdf0000      62K     /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64/libverify.so
0x00007fd4040f0000      43K     /lib64/librt-2.12.so
0x00007fd4042f8000      88K     /lib64/libgcc_s-4.4.7-20120601.so.1
0x00007fd40450e000      582K    /lib64/libm-2.12.so
0x00007fd404792000      963K    /usr/lib64/libstdc++.so.6.0.13
0x00007fd404a98000      14352K  /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64/server/libjvm.so
0x00007fd405abf000      1879K   /lib64/libc-2.12.so
0x00007fd405e53000      19K     /lib64/libdl-2.12.so
0x00007fd406057000      58K     /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64/jli/libjli.so
0x00007fd406266000      86K     /lib64/libz.so.1.2.3
0x00007fd40647c000      139K    /lib64/libpthread-2.12.so
0x00007fd406699000      155K    /lib64/ld-2.12.so

打印的信息分别为:共享对象的起始地址、映射大小、共享对象路径的全程。

2)、jmap -heap pid:查看堆使用情况

[root@iZ2ze1224b1em0jij7qlssZ bin]# jmap -heap 25699 
Attaching to process ID 25699, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.212-b04

using thread-local object allocation.
Parallel GC with 2 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 4217372672 (4022.0MB)
   NewSize                  = 88080384 (84.0MB)
   MaxNewSize               = 1405616128 (1340.5MB)
   OldSize                  = 176160768 (168.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 637534208 (608.0MB)
   used     = 326762024 (311.62454986572266MB)
   free     = 310772184 (296.37545013427734MB)
   51.25403780686228% used
From Space:
   capacity = 524288 (0.5MB)
   used     = 116368 (0.1109771728515625MB)
   free     = 407920 (0.3890228271484375MB)
   22.1954345703125% used
To Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
PS Old Generation
   capacity = 238551040 (227.5MB)
   used     = 59055768 (56.319969177246094MB)
   free     = 179495272 (171.1800308227539MB)
   24.7560304075807% used

11561 interned Strings occupying 978776 bytes.

3)、jmap -histo pid:查看堆中对象数量和大小

[root@iZ2ze1224b1em0jij7qlssZ opt]# jmap -histo 25699
 num     #instances         #bytes  class name
----------------------------------------------
   1:       4134436       99226464  java.util.ArrayList
   2:       2062243       65991776  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
   3:       2055722       65783104  java.util.concurrent.FutureTask
   4:       2055802       49339248  java.util.concurrent.LinkedBlockingQueue$Node
   5:        916752       36670080  com.miu360.area.LatLng
   6:       2055722       32891552  com.miu360.taxi.location.module.CoreThread$InsertDevicesRunnable$1
   7:         10615       25663720  [I
   8:         15012        5289088  [Ljava.lang.Object;
   9:         79300        5276104  [C
  10:         28175        3322512  [B
  11:         62512        1500288  java.lang.String
  12:         22163         886520  sun.nio.cs.UTF_8$Decoder

打印的信息分别是:序列号、对象的数量、这些对象的内存占用大小、这些对象所属的类的全限定名

如果是内部类,类名的开头会加上*,如果加上live子参数的话,如jmap -histo:live pid,这个命名会触发一次FUll GC,只统计存活对象

4)、jmap -dump:format=b,file=heapdump pid:将内存使用的详细情况输出到文件

[root@iZ2ze1224b1em0jij7qlssZ opt]# jmap -dump:format=b,file=heapdump 25699
Dumping heap to /opt/heapdump ...
Heap dump file created

     然后使用jhat命令查看该文件:jhat -port 4000 文件名 ,在浏览器中访问http:localhost:4000/

[root@iZ2ze1224b1em0jij7qlssZ opt]# jhat -port 4000 heapdump 
Reading from heapdump...
Dump file created Wed Jul 14 13:45:56 CST 2021
Snapshot read, resolving...
Resolving 1630999 objects...
Chasing references, expect 326 dots......................................................................................................................................................................................................................................................................................................................................
Eliminating duplicate references......................................................................................................................................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 4000
Server is ready.

总结:

该命令适用的场景是程序内存不足或者GC频繁,这时候很可能是内存泄漏。通过用以上命令查看堆使用情况、大量对象被持续引用等情况。

4、jstat

主要是对java应用程序的资源和性能进行实时的命令行监控,包括了对heap size和垃圾回收状况的监控。

 jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

option:我们经常使用的选项有gc、gcutil

vmid:java进程id

interval:间隔时间,单位为毫秒

count:打印次数

1)、jstat -gc PID 5000 20 :垃圾回收统计

5秒钟打印一次,一共打印20次。

[root@iZ2ze1224b1em0jij7qlssZ opt]# jstat -gc 25699 5000 20
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
512.0  512.0   0.0    0.0   623104.0 72399.2   228352.0   48528.4   28800.0 28049.9 2944.0 2763.6  23000   65.580   3      0.365   65.945
512.0  512.0   0.0    0.0   623104.0 72399.2   228352.0   48528.4   28800.0 28049.9 2944.0 2763.6  23000   65.580   3      0.365   65.945
512.0  512.0   0.0    0.0   623104.0 72399.2   228352.0   48528.4   28800.0 28049.9 2944.0 2763.6  23000   65.580   3      0.365   65.945

S0C:年轻代第一个Survivor区的大小(字节)
S1C:年轻代第二个Survivor区的大小(字节)
S0U:年轻代第一个Survivor区的使用大小(字节)
S1U:年轻代第二个Survivor区的使用大小(字节)
EC:年轻代中Eden区的大小(字节)
EU:年轻代中Eden区的使用大小(字节)
OC:老年代大小(字节)
OU:老年代使用大小(字节)
MC:方法区大小(字节)
MU:方法区使用大小(字节)
CCSC:压缩类空间大小(字节)
CCSU:压缩类空间使用大小(字节)
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

ps:之前的PC 和PU 被MC MU取代了。(永久代)

2)、jstat -gccapacity pid 5000 20 : 堆内存统计

[root@iZ2ze1224b1em0jij7qlssZ opt]# jstat -gccapacity  25699 5000 20
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
 86016.0 1372672.0 624128.0  512.0  512.0 623104.0   172032.0  2745856.0   228352.0   228352.0      0.0 1075200.0  28800.0      0.0 1048576.0   2944.0  23000     3
 86016.0 1372672.0 624128.0  512.0  512.0 623104.0   172032.0  2745856.0   228352.0   228352.0      0.0 1075200.0  28800.0      0.0 1048576.0   2944.0  23000     3
 86016.0 1372672.0 624128.0  512.0  512.0 623104.0   172032.0  2745856.0   228352.0   228352.0      0.0 1075200.0  28800.0      0.0 1048576.0   2944.0  23000     3

NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0C:第一个Survivor区大小
S1C:第二个Survivor区的大小
EC:Eden区的大小
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:当前老年代大小
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代gc次数
FGC:老年代GC次数

3)、jstat -gcnew pid 5000 20 : 新生代垃圾回收统计

[root@iZ2ze1224b1em0jij7qlssZ opt]# jstat -gcnew   25699 5000 20
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
 512.0  512.0    0.0    0.0 15  15  512.0 623104.0 276460.9  23000   65.580
 512.0  512.0    0.0    0.0 15  15  512.0 623104.0 276460.9  23000   65.580
 512.0  512.0    0.0    0.0 15  15  512.0 623104.0 276460.9  23000   65.580
 512.0  512.0    0.0    0.0 15  15  512.0 623104.0 276466.3  23000   65.580

S0C: 第一个Survivor区大小
S1C: 第二个Survivor区的大小
S0U: 第一个Survivor区的使用大小
S1U: 第二个Survivor区的使用大小
TT: 对象在新生代存活的次数
MTT: 对象在新生代存活的最大次数
DSS: 期望的Survivor区大小
EC: Eden区的大小
EU: Eden区的使用大小
YGC: 年轻代垃圾回收次数
YGCT: 年轻代垃圾回收消耗时间

4)、jstat -gcnewcapacity pid 5000 20 : 新生代内存统计

[root@iZ2ze1224b1em0jij7qlssZ opt]# jstat  -gcnewcapacity   25699 5000 20
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC 
   86016.0  1372672.0   624128.0 457216.0    512.0 457216.0    512.0  1371648.0   623104.0 23000     3
   86016.0  1372672.0   624128.0 457216.0    512.0 457216.0    512.0  1371648.0   623104.0 23000     3
   86016.0  1372672.0   624128.0 457216.0    512.0 457216.0    512.0  1371648.0   623104.0 23000     3

NGCMN:新生代最小容量
NGCMX:新生代最大容量
NGC:当前新生代容量
S0CMX:第一个Survivor区最大大小
S0C:第一个Survivor区当前大小
S1CMX:第二个Survivor区最大大小
S1C:第二个Survivor区当前大小
ECMX:Eden区最大大小
EC:Eden区当前大小
YGC:年轻代垃圾回收次数

5)、jstat -gcold pid 5000 20 : 老年代垃圾回收统计

[root@iZ2ze1224b1em0jij7qlssZ opt]# jstat  -gcold  25699 5000 20
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT   
 28800.0  28049.9   2944.0   2763.6    228352.0     48528.4  23000     3    0.365   65.945
 28800.0  28049.9   2944.0   2763.6    228352.0     48528.4  23000     3    0.365   65.945
 28800.0  28049.9   2944.0   2763.6    228352.0     48528.4  23000     3    0.365   65.945

MC: 方法区大小
MU: 方法区使用大小
CCSC: 压缩类空间大小
CCSU: 压缩类空间使用大小
OC: 老年代大小
OU: 老年代使用大小
YGC: 年轻代垃圾回收次数
FGC: 老年代垃圾回收次数
FGCT: 老年代垃圾回收消耗时间
GCT: 垃圾回收消耗总时间

6)、jstat -gcoldcapacity pid 5000 20 : 老年代内存统计

[root@iZ2ze1224b1em0jij7qlssZ opt]# jstat  -gcoldcapacity   25699 5000 20
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT   
   172032.0   2745856.0    228352.0    228352.0 23000     3    0.365   65.945
   172032.0   2745856.0    228352.0    228352.0 23000     3    0.365   65.945
   172032.0   2745856.0    228352.0    228352.0 23000     3    0.365   65.945

OGCMN: 老年代最小容量
OGCMX: 老年代最大容量
OGC: 当前老年代大小
OC: 老年代大小
YGC: 年轻代垃圾回收次数
FGC: 老年代垃圾回收次数
FGCT: 老年代垃圾回收消耗时间
GCT: 垃圾回收消耗总时间

7)、jstat -gcmetacapacity pid 5000 20 : 元数据空间统计

[root@iZ2ze1224b1em0jij7qlssZ opt]# jstat  -gcmetacapacity  25699 5000 20
   MCMN       MCMX        MC       CCSMN      CCSMX       CCSC     YGC   FGC    FGCT     GCT   
       0.0  1075200.0    28800.0        0.0  1048576.0     2944.0 23000     3    0.365   65.945
       0.0  1075200.0    28800.0        0.0  1048576.0     2944.0 23000     3    0.365   65.945
       0.0  1075200.0    28800.0        0.0  1048576.0     2944.0 23000     3    0.365   65.945

MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

8)、jstat -gcutil PID 5000 20 :总结垃圾回收统计

[root@iZ2ze1224b1em0jij7qlssZ opt]# jstat -gcutil 25699 5000 20
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
  0.00   0.00  27.10  21.25  97.40  93.87  23000   65.580     3    0.365   65.945
  0.00   0.00  27.10  21.25  97.40  93.87  23000   65.580     3    0.365   65.945
  0.00   0.00  27.10  21.25  97.40  93.87  23000   65.580     3    0.365   65.945
  0.00   0.00  27.10  21.25  97.40  93.87  23000   65.580     3    0.365   65.945

S0:第一个Servivor区当前使用比例
S1:第二个Servivor区当前使用比例
E:Eden区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩使用比例
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间

5、jhat

主要用来解析java堆dump并启动一个web服务器,然后就可以在浏览器中查看堆的dump文件了。

jhat heapdump

这个命令将heapdump文件转换成html格式,并且启动一个http服务,默认端口为7000。在浏览器中访问 http:localhost:7000/ 就能打开页面

如果端口冲突,可以使用以下命令指定端口:jhat -port 4000 heapdump

6、jinfo

jinfo可以用来查看正在运行的java运用程序的扩展参数,甚至支持在运行时动态地更改部分参数。

基本使用语法如下: jinfo -< option > < pid > ,其中option可以为以下信息:

-flag< name >: 打印指定java虚拟机的参数值

-flag [+|-]< name >:设置或取消指定java虚拟机参数的布尔值

-flag < name >=< value >:设置指定java虚拟机的参数的值

查看当前的运行参数:

[root@iZ2ze1224b1em0jij7qlssZ opt]# jinfo 25699
Attaching to process ID 25699, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.212-b04
Java System Properties:

java.runtime.name = OpenJDK Runtime Environment
java.vm.version = 25.212-b04
sun.boot.library.path = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/amd64
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
file.encoding.pkg = sun.io
java.vm.name = OpenJDK 64-Bit Server VM
sun.os.patch.level = unknown
sun.java.launcher = SUN_STANDARD
user.country = US
user.dir = /var/server/TaxiLocationServer2
java.vm.specification.name = Java Virtual Machine Specification
java.runtime.version = 1.8.0_212-b04
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/endorsed
java.io.tmpdir = /tmp
line.separator = 

java.vm.specification.vendor = Oracle Corporation
os.name = Linux
sun.jnu.encoding = UTF-8
jetty.git.hash = d5fc0523cfa96bfebfbda19606cad384d772f04c
java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.specification.name = Java Platform API Specification
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 2.6.32-754.14.2.el6.x86_64
user.home = /root
user.timezone = Asia/Shanghai
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
user.name = root
java.class.path = TaxiLocationServer2.jar
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = TaxiLocationServer2.jar
java.home = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre
user.language = en
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.X11.XToolkit
java.vm.info = mixed mode
java.version = 1.8.0_212
java.ext.dirs = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/resources.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/rt.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/jsse.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/jce.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/charsets.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/lib/jfr.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.212.b04-0.el6_10.x86_64/jre/classes
java.vendor = Oracle Corporation
file.separator = /
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.cpu.isalist = 

VM Flags:
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=264241152 -XX:MaxHeapSize=4217372672 -XX:MaxNewSize=1405616128 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=88080384 -XX:OldSize=176160768 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
Command line:  

下面的命令显示了新生代对象晋升到老年代对象的最大年龄。在运行程序运行时并没有指定这个参数,但是通过jinfo,可以查看这个参数的当前的值。

[root@iZ2ze1224b1em0jij7qlssZ opt]# jinfo -flag MaxTenuringThreshold 25699
-XX:MaxTenuringThreshold=15

下面的命令显示是否打印gc详细信息:

[root@iZ2ze1224b1em0jij7qlssZ opt]# jinfo -flag PrintGCDetails  25699
-XX:-PrintGCDetails

下面的命令在运用程序运行时动态打开打印详细gc信息开关:

root@iZ2ze1224b1em0jij7qlssZ opt]# jinfo -flag +PrintGCDetails  25699
[root@iZ2ze1224b1em0jij7qlssZ opt]# jinfo -flag PrintGCDetails  25699
-XX:+PrintGCDetails

注意事项:jinfo虽然可以在java程序运行时动态地修改虚拟机参数,但并不是所有的参数都支持动态修改。

7、jcmd

在JDK 1.7之后,新增了一个命令行工具jcmd。它是一个多功能工具,可以用来导出堆,查看java进程,导出线程信息,执行GC等。jcmd拥有jmap的大部分功能,Oracle官方建议使用jcmd代替jmap。

[root@iZ2ze1224b1em0jij7qlssZ opt]# jcmd -l
26949 org.apache.zookeeper.server.quorum.QuorumPeerMain /var/zookeeper-3.3.6/bin/../conf/zoo.cfg
10220 inner-0.0.1-SNAPSHOT.jar

针对每一个虚拟机,可以使用help命令列出该虚拟机支持的所有命令:

[root@iZ2ze1224b1em0jij7qlssZ opt]# jcmd  25699 help
25699:
The following commands are available:
VM.native_memory
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
help

For more information about a specific command use 'help <command>'.

子命令含义:
  VM.native_memory
  VM.commercial_features
  GC.rotate_log
  ManagementAgent.stop
  ManagementAgent.start_local
  ManagementAgent.start
  Thread.print, 打印线程栈信息
  GC.class_histogram, 查看系统中类统计信息
  GC.heap_dump, 导出堆信息,与jmap -dump功能一样
  GC.run_finalization, 触发finalize()
  GC.run, 触发gc()
  VM.uptime, VM启动时间
  VM.flags, 获取JVM启动参数
  VM.system_properties, 获取系统Properties
  VM.command_line, 启动时命令行指定的参数
  VM.version
  help

示例:

[root@iZ2ze1224b1em0jij7qlssZ opt]# jcmd  25699 VM.uptime
25699:
10286927.045 s
[root@iZ2ze1224b1em0jij7qlssZ opt]# jcmd  25699 VM.flags
25699:
-XX:CICompilerCount=2 -XX:InitialHeapSize=264241152 -XX:MaxHeapSize=4217372672 -XX:MaxNewSize=1405616128 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=88080384 -XX:OldSize=176160768 -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
[root@iZ2ze1224b1em0jij7qlssZ opt]# jcmd  25699 VM.command_line
25699:
VM Arguments:
java_command: TaxiLocationServer2.jar
java_class_path (initial): TaxiLocationServer2.jar
Launcher Type: SUN_STANDARD

8、可视化监控工具(JConsole、JVisualVM)

集上面之大成,并提供了可视化的界面;还可以监控远程Java服务;支持监控JMX。

JVisualVM比JConsole更强大:支持对CPU、内存运行进行采样、配置。推荐用JVisualVM。

JConsole监控页面示例:

JVisualVM监控页面示例:

参考:

https://www.cnblogs.com/z-sm/p/6745375.html

https://blog.csdn.net/wangzhongshun/article/details/112545871

https://blog.csdn.net/yx0628/article/details/80958488

原文地址:https://www.cnblogs.com/sfnz/p/15010163.html