JDK命令行工具

目录

1.JDK的命令行工具

1.1 常用工具

名称

作用

jps

JVM Process Status Tool,显示系统中所有的Hotspot虚拟机进程

jstat

JVM Statistics Monitoring Tool,用于收集HotSpot虚拟机各方面的运行数据

jinfo

Configuration info for java,显示虚拟机配置信息

jmap

Memory Map for java,生成虚拟机的内存转储快照(heapdump文件)

jhat

JVM Heapdump Browser,用于分析heapdump文件,会建立一个HTTP/HTML服务器,用户可以在浏览器上查看分析结果

jstack

Stack Trace for java,显示虚拟机的线程快照

 

1.2 jps:虚拟机进程状况工具

JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程,类似于Linux中的ps命令。

$ jps -help
usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]
​
Definitions:
    <hostid>:      <hostname>[:<port>]

参数含义:

[xxxx@xxxxx01 ~]$ jps
25052 Bootstrap
13210 Jps
[xxxx@xxxxx01 ~]$ jps -q  //仅输出虚拟机进程id
25052
13269
[xxxx@xxxxx01 ~]$ jps -m  //输出虚拟机进程启用的时候传递给主类main()函数的参数
25052 Bootstrap
13284 Jps -m
[xxxx@xxxxx01 ~]$ jps -l  //输出主类的全类名
25052 com.xxxx.boot.Bootstrap
13309 sun.tools.jps.Jps
[xxxx@xxxxx01 ~]$ jps -v  //输出虚拟机进程启动时JVM参数
25052 Bootstrap -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.io.tmpdir=/tmp -Djava.net.preferIPv6Addresses=false -Xmx2g -Xms128m -XX:SurvivorRatio=8 -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/logs/leaf.oom.log -XX:ReservedCodeCacheSize=128m -XX:InitialCodeCacheSize=128m -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+UseConcMarkSweepGC -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/opt/logs/xxx.gc -XX:CMSFullGCsBeforeCompaction=0 -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=80 -Xloggc:/var/xxx/logs/xxx.gc.log -XX:ErrorFile=/var/xxx/logs/xxx.vmerr.log -XX:HeapDumpPath=/var/xxx/logs/xxx.heaperr.log -Djetty.context=/ -Djetty.logs=/var/xxxxx/logs/ -Djetty.webroot=/opt/xxx/yyy -Djetty.port=8080 -DSTOP.PORT=38415
13335 Jps -Dapplication.home=/usr/local/jdk1.7.0_76 -Xms8m
[xxxx@xxxxx01 ~]$ jps -V  //有啥作用?
25052 Bootstrap
13670 Jps

常用命令:

jps -lmv

[xxxx@xxxxx01 ~]$ jps -lmv
25052 com.xxx.mms.boot.Bootstrap -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.io.tmpdir=/tmp -Djava.net.preferIPv6Addresses=false -Xmx2g -Xms128m -XX:SurvivorRatio=8 -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/logs/leaf.oom.log -XX:ReservedCodeCacheSize=128m -XX:InitialCodeCacheSize=128m -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+UseConcMarkSweepGC -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/opt/logs/leaf.gc -XX:CMSFullGCsBeforeCompaction=0 -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=80 -Xloggc:/var/logs//.gc.log -XX:ErrorFile=/var/logs//.vmerr.log -XX:HeapDumpPath=/var/logs//.heaperr.log  -Djetty.context=/ -Djetty.logs=/var/logs/ -Djetty.webroot=/opt/xxx/leaf -Djetty.port=8080 -DSTOP.PORT=38415
13685 sun.tools.jps.Jps -lmv -Dapplication.home=/usr/local/jdk1.7.0_76 -Xms8m

 

1.3 jstat:虚拟机统计信息监控工具

用于监视虚拟机各种运行状态信息的工具。包括类装载、内存、垃圾收集、JIT编译等运行数据。

[xxxx@xxxxx01 ~]$ jstat -help
Usage: jstat -help|-options
       jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
​
Definitions:
  <option>      An option reported by the -options option
  <vmid>        Virtual Machine Identifier. A vmid takes the following form:
                     <lvmid>[@<hostname>[:<port>]]
                Where <lvmid> is the local vm identifier for the target
                Java virtual machine, typically a process id; <hostname> is
                the name of the host running the target Java virtual machine;
                and <port> is the port number for the rmiregistry on the
                target host. See the jvmstat documentation for a more complete
                description of the Virtual Machine Identifier.
  <lines>       Number of samples between header lines.
  <interval>    Sampling interval. The following forms are allowed:
                    <n>["ms"|"s"]
                Where <n> is an integer and the suffix specifies the units as
                milliseconds("ms") or seconds("s"). The default units are "ms".
  <count>       Number of samples to take before terminating.
  -J<flag>      Pass <flag> directly to the runtime system.
[xxxx@xxxxx01 ~]$ jstat -options

命令格式:

jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
     //option                   //vmid  //查询间隔    //查询次数 
 -t参数可以在输出信息前加一个timestamp列,显示程序的运行时间
 -h参数可以在周期性数据输出时,输出多少行数据后,跟着输出一个表头信息。
 -interval参数用于指定统计数据的输出周期,单位是毫秒
 -count参数用于指定输出的次数

把options按功能划分一下

-class           //显示ClassLoader相关信息。             监视类装载、卸载数量、总空间以及类装载所花的时间
-gc              //显现与GC相关的堆信息。                 监视Java堆状况,包括Eden区、两个Survior区、老年代、永久代等容量、已用空间、GC时间统计等信息
-gccapacity      //显示各个代的容量和使用情况。            监视内容与-gc基本相同,但是输出主要关注Java堆各个区域使用的最大、最小空间
-gcutil          //显示垃圾收集信息。                    监视内容与-gc基本相同,但是输出主要关注已使用空间占总空间的百分比
-gccause         //显示垃圾收集信息(同-gcutil),同时显示最后一次或当前正在发生的垃圾收集的诱发原因。
-gcnew           //显示新生代信息。                      监视新生代GC情况
-gcnewcapacity   //显示新生代大小与使用情况。             监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间
-gcold           //显示老年代信息。                     监视老年代GC情况
-gcoldcapacity   //显示老年代大小与使用使用。             监视内容与-gcold基本相同,输出主要关注使用到的最大、最小空间
-gcpermcapacity  //输出永久代使用到的最大、最小空间
-compiler         //显示JIT编译的相关信息。              输出JIT编译期编译过的方法、耗时等信息
-printcompilation //输出已经被JIT编译过的方法

 

-class参数

[xxxx@xxxxx01 ~]$ jstat -class 25052 100ms 5
Loaded  Bytes  Unloaded  Bytes     Time
  9285 18916.1        0     0.0       8.54
  9285 18916.1        0     0.0       8.54
  9285 18916.1        0     0.0       8.54
  9285 18916.1        0     0.0       8.54
  9285 18916.1        0     0.0       8.54
​
Loaded:载入类的数量
Bytes:载入类的合计大小
Unloaded:卸载类的数量
Bytes:卸载类的合计大小
Time:加载类和卸载类上花费的时间

 

-gc参数
[xxxx@xxxxx01 ~]$ jstat -gc 25052 100ms 5
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT
4352.0 4352.0  0.0   496.2  34944.0  18208.5   94960.0    60879.8   262144.0 57052.6  12987   54.255  268     1.606   55.861
4352.0 4352.0  0.0   496.2  34944.0  18208.5   94960.0    60879.8   262144.0 57052.6  12987   54.255  268     1.606   55.861
4352.0 4352.0  0.0   496.2  34944.0  18208.5   94960.0    60879.8   262144.0 57052.6  12987   54.255  268     1.606   55.861
4352.0 4352.0  0.0   496.2  34944.0  18208.5   94960.0    60879.8   262144.0 57052.6  12987   54.255  268     1.606   55.861
4352.0 4352.0  0.0   496.2  34944.0  18208.5   94960.0    60879.8   262144.0 57052.6  12987   54.255  268     1.606   55.861
​
S0C:年轻代中第一个survivor(幸存区)的容量 (KB) 
S1C:年轻代中第二个survivor(幸存区)的容量 (KB) 
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (KB) 
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (KB) 
EC:年轻代中Eden(伊甸园)的容量 (KB) 
EU:年轻代中Eden(伊甸园)目前已使用空间 (KB) 
OC:Old代的容量 (KB) 
OU:Old代目前已使用空间 (KB) 
PC:Perm(持久代)的容量 (KB) 
PU:Perm(持久代)目前已使用空间 (KB) 
YGC:从应用程序启动到采样时年轻代中gc次数 
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s) 
FGC:从应用程序启动到采样时old代(全gc)gc次数 
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s) 
GCT:从应用程序启动到采样时gc用的总时间(s) 

 

-gccapacity参数

[xxxx@xxxxx01 ~]$ jstat -gccapacity 25052 100ms 5
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC
 43648.0 340736.0  43648.0 4352.0 4352.0  34944.0    87424.0  1756416.0    94960.0    94960.0 262144.0 262144.0 262144.0 262144.0  12989   268
 43648.0 340736.0  43648.0 4352.0 4352.0  34944.0    87424.0  1756416.0    94960.0    94960.0 262144.0 262144.0 262144.0 262144.0  12989   268
 43648.0 340736.0  43648.0 4352.0 4352.0  34944.0    87424.0  1756416.0    94960.0    94960.0 262144.0 262144.0 262144.0 262144.0  12989   268
 43648.0 340736.0  43648.0 4352.0 4352.0  34944.0    87424.0  1756416.0    94960.0    94960.0 262144.0 262144.0 262144.0 262144.0  12989   268
 43648.0 340736.0  43648.0 4352.0 4352.0  34944.0    87424.0  1756416.0    94960.0    94960.0 262144.0 262144.0 262144.0 262144.0  12989   268
​
NGCMN:年轻代(young)中初始化(最小)的大小 (KB) 【New Generation Capacity Min】
NGCMX:年轻代(young)的最大容量 (KB) 
NGC:年轻代(young)中当前的容量 (KB) 
​
OGCMN:old代中初始化(最小)的大小 (KB) 
OGCMX:old代的最大容量 (KB) 
PGCMN:perm代中初始化(最小)的大小 (KB) 
PGCMX:perm代的最大容量 (KB)

 

-gcutil参数

[xxxx@xxxxx01 ~]$ jstat -gcutil 25052 100ms 5
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
  5.52   0.00  73.20  64.11  21.76  12990   54.264   268    1.606   55.870
  5.52   0.00  73.20  64.11  21.76  12990   54.264   268    1.606   55.870
  5.52   0.00  73.20  64.11  21.76  12990   54.264   268    1.606   55.870
  5.52   0.00  73.20  64.11  21.76  12990   54.264   268    1.606   55.870
  5.52   0.00  73.20  64.11  21.76  12990   54.264   268    1.606   55.870
​
S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比 
S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比 
E:年轻代中Eden(伊甸园)已使用的占当前容量百分比 
O:old代已使用的占当前容量百分比
P:perm代已使用的占当前容量百分比 

 

-gccause参数

[xxxx@xxxxx01 ~]$ jstat -gccause 25052 100ms 5
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC
  4.74   0.00  57.65  64.11  21.76  12992   54.272   268    1.606   55.878 Allocation Failure   No GC
  4.74   0.00  57.65  64.11  21.76  12992   54.272   268    1.606   55.878 Allocation Failure   No GC
  4.74   0.00  57.69  64.11  21.76  12992   54.272   268    1.606   55.878 Allocation Failure   No GC
  4.74   0.00  57.69  64.11  21.76  12992   54.272   268    1.606   55.878 Allocation Failure   No GC
  4.74   0.00  57.70  64.11  21.76  12992   54.272   268    1.606   55.878 Allocation Failure   No GC
​
LGCC:上次GC的原因【Last GC Cause】
GCC:当前GC的原因

 

-gcnew参数

[xxxx@xxxxx01 ~]$ jstat -gcnew 25052 100ms 5
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
4352.0 4352.0  357.9    0.0 15  15 2176.0  34944.0   8722.8  12996   54.285
4352.0 4352.0  357.9    0.0 15  15 2176.0  34944.0   8736.6  12996   54.285
4352.0 4352.0  357.9    0.0 15  15 2176.0  34944.0   8736.6  12996   54.285
4352.0 4352.0  357.9    0.0 15  15 2176.0  34944.0   8736.6  12996   54.285
4352.0 4352.0  357.9    0.0 15  15 2176.0  34944.0   8736.6  12996   54.285
​
TT:新生代对象晋升到老年代的年龄。Tenuring threshold(提升阈值)
MTT:新生代对象晋升到老年代的年龄的最大值。最大的tenuring threshold
DSS:所需的Survivor大小。survivor区域大小 (KB)

 

-gcnewcapacity

[xxxx@xxxxx01 ~]$ jstat -gcnewcapacity 25052 100ms 5
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
   43648.0   340736.0    43648.0  34048.0   4352.0  34048.0   4352.0   272640.0    34944.0 12997   268
   43648.0   340736.0    43648.0  34048.0   4352.0  34048.0   4352.0   272640.0    34944.0 12997   268
   43648.0   340736.0    43648.0  34048.0   4352.0  34048.0   4352.0   272640.0    34944.0 12997   268
   43648.0   340736.0    43648.0  34048.0   4352.0  34048.0   4352.0   272640.0    34944.0 12997   268
   43648.0   340736.0    43648.0  34048.0   4352.0  34048.0   4352.0   272640.0    34944.0 12997   268
​
S0CMX:最大的S0空间 (KB) 
S1CMX:最大的S1空间(KB)
ECMX:最大eden空间 (KB)

 

-compiler

[xxxx@xxxxx01 ~]$ jstat -compiler 25052 100ms 5
Compiled Failed Invalid   Time   FailedType FailedMethod
    3093      0       0    34.14          0
    3093      0       0    34.14          0
    3093      0       0    34.14          0
    3093      0       0    34.14          0
    3093      0       0    34.14          0
​
Compiled:编译任务执行的次数
Failed:编译失败的次数
Invalid:编译不可用的次数
FailedType:最后一次编译失败的类型
FailedMethod:最后一次编译失败的类名和方法名

 

-printcompilation参数

[xxxx@xxxxx01 ~]$ jstat -printcompilation 25052 100ms 5
Compiled  Size  Type Method
    3093   2036    1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next
    3093   2036    1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next
    3093   2036    1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next
    3093   2036    1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next
    3093   2036    1 com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl$PrologDriver next
​
Compiled:编译任务执行的次数
Size:方法字节码的字节数
Type:编译类型
Method:编译方法的类名和方法名。类名使用”/” 代替 “.” 作为空间分隔符. 方法名是给出类的方法名. 格式是同HotSpot - XX:+PrintComplation选项一致

 

1.4 jinfo:java配置信息查看工具

jinfo(JVM Configuration info)这个命令作用是实时查看和调整虚拟机运行参数,甚至支持在运行时修改部分参数。

jps -v命令只能查看到显示指定的参数,如果想要查看未被显示指定的参数的值就要使用jinfo口令

$ jinfo
Usage:
    jinfo [option] <pid>
        (to connect to running process)
    jinfo [option] <executable <core>
        (to connect to a core file)
    jinfo [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)
​
where <option> is one of:
    -flag <name>         to print the value of the named VM flag
    -flag [+|-]<name>    to enable or disable the named VM flag
    -flag <name>=<value> to set the named VM flag to the given value
    -flags               to print VM flags  //不管用
    -sysprops            to print Java system properties //不管用
    <no option>          to print both of the above //不管用
    -h | -help           to print this help message
jinfo命令格式:
jinfo [option] [args] LVMID

option如下

-flag <name>:打印JVM指定参数值
-flag [+|-]<name>:设置指定JVM参数的布尔值
-flag <name>=<value>:设置指定JVM参数的值

使用示例:

1.查看参数值

[xxxx@xxxxx01 ~]$ jinfo -flag SurvivorRatio 66636
-XX:SurvivorRatio=8

2.修改参数值

[xxxx@xxxxx01 ~]$ jinfo -flag +PrintGCDetails 66636

 

1.5 jmap:Java内存映射工具

jmap(Memory Map for Java)命令用于生成堆转储快照heapdump。

如果不使用这个命令,还可以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM的时候生成。

$ jmap
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
    -permstat            to print permanent generation 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

jmap命令格式:jmap [option] <pid>

option参数如下:

dump : 生成堆转储快照
finalizerinfo : 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象
heap : 显示Java堆详细信息
histo : 显示堆中对象的统计信息
permstat : to print permanent generation statistics
F : 当-dump没有响应时,强制生成dump快照

常用命令

1.生成dump文件

jmap -dump:live,format=b,file=<filename> pid
//dump堆到文件,format=b指定输出格式为二进制知识,live指明是活着的对象,file指定文件名

使用示例:

[xxxx@xxxxx01 ~]$ jmap -dump:live,format=b,file=dump.hprof 25052
Dumping heap to /home/xxxx/dump.hprof ...
Heap dump file created 

2. 输出堆的概要信息

jmap -heap pid
使用示例:
[xxxx@xxxxx01 ~]$ jmap -heap 25052
Attaching to process ID 25052, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.76-b04
​
using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC
​
Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 2147483648 (2048.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 348913664 (332.75MB)
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 268435456 (256.0MB)
   MaxPermSize      = 268435456 (256.0MB)
   G1HeapRegionSize = 0 (0.0MB)
​
Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 43974656 (41.9375MB)
   used     = 37745000 (35.996437072753906MB)
   free     = 6229656 (5.941062927246094MB)
   85.83353102296013% used
Eden Space:
   capacity = 39124992 (37.3125MB)
   used     = 37745000 (35.996437072753906MB)
   free     = 1379992 (1.3160629272460938MB)
   96.47286317655988% used
From Space:
   capacity = 4849664 (4.625MB)
   used     = 0 (0.0MB)
   free     = 4849664 (4.625MB)
   0.0% used
To Space:
   capacity = 4849664 (4.625MB)
   used     = 0 (0.0MB)
   free     = 4849664 (4.625MB)
   0.0% used
concurrent mark-sweep generation:
   capacity = 97239040 (92.734375MB)
   used     = 20550976 (19.59893798828125MB)
   free     = 76688064 (73.13543701171875MB)
   21.134490838247682% used
Perm Generation:
   capacity = 268435456 (256.0MB)
   used     = 58222856 (55.52564239501953MB)
   free     = 210212600 (200.47435760498047MB)
   21.689704060554504% used
​
20990 interned Strings occupying 2568944 bytes.

3.-histo(histogram 直方图)

打印堆的对象统计,包括对象数、内存大小等等 (因为在dump:live前会进行full gc,如果带上live则只统计活对象,因此不加live的堆大小要大于加live堆的大小 )

[xxxx@xxxxx01 ~]$ jmap -histo:live 25052 | more
​
 num     #instances         #bytes  class name
----------------------------------------------
   1:        102722       14750176  <constMethodKlass>
   2:        102722       13161600  <methodKlass>
   3:          9231       10948488  <constantPoolKlass>
   4:         47988        7325624  [C
   5:          9226        6761096  <instanceKlassKlass>
   6:          7607        6037856  <constantPoolCacheKlass>
   7:         32606        3836968  [B
   8:          4726        2321712  <methodDataKlass>
   9:         46337        1112088  java.lang.String
  10:          9936         956392  java.lang.Class
  11:         35328         847872  io.netty.buffer.PoolThreadCache$MemoryRegionCache$Entry
  12:         15365         807448  [[I
  13:         13630         805176  [S
  14:         18214         582848  java.util.concurrent.ConcurrentHashMap$HashEntry
  15:          4182         485760  [Ljava.lang.Object;
  16:         10664         426560  java.util.TreeMap$Entry
  17:           693         376992  <objArrayKlassKlass>
  18:         10739         343648  java.util.HashMap$Entry
  19:          4139         331120  java.lang.reflect.Method
  20:          2326         282960  [Ljava.util.HashMap$Entry;
  21:          9694         232656  java.lang.Long
  22:         14327         229232  java.lang.Object
  23:          1348         209016  [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;
  24:          1716         170496  [I
  25:          4052         162080  java.util.LinkedHashMap$Entry

其中,class name是对象类型

B  byte
C  char
D  double
F  float
I  int
J  long
Z  boolean
[  数组,如[I表示int[]
[L+类名 其他对象

 

1.6 jhat:虚拟机堆快照分析工具

jhat(JVM Heap Analysis Tool)与jmap配合使用,来分析jmap生成的heapdump。

jhat内置了一个HTTP/HTML服务器,可以在浏览器中查看dump文件的分析结果。

一般不用jhat来分析dump文件,jhat功能比较简陋。

一般会download dump文件到本地,使用Eclipse Memory Analyzer(MAT)等工具进行分析。

$ jhat -help
Usage:  jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>-J<flag>          Pass <flag> directly to the runtime system. For
        example, -J-mx512m to use a maximum heap size of 512MB
  -stack false:     Turn off tracking object allocation call stack.
  -refs false:      Turn off tracking of references to objects
  -port <port>:     Set the port for the HTTP server.  Defaults to 7000
  -exclude <file>:  Specify a file that lists data members that should
        be excluded from the reachableFrom query.
  -baseline <file>: Specify a baseline object dump.  Objects in
        both heap dumps with the same ID and same class will
        be marked as not being "new".
  -debug <int>:     Set debug level.
          0:  No debug output
          1:  Debug hprof file parsing
          2:  Debug hprof file parsing, no server
  -version          Report version number
  -h|-help          Print this help and exit
  <file>            The file to read
​
For a dump file that contains multiple heap dumps,
you may specify which dump in the file
by appending "#<number>" to the file name, i.e. "foo.hprof#3".
​
All boolean options default to "true"

常用命令:

jhat <filename>
使用示例:
$ jhat java_pid82395.0001.hprof
Reading from java_pid82395.0001.hprof...
Dump file created Fri Jan 04 22:45:37 CST 2019
Snapshot read, resolving...
Resolving 2043422 objects...
Chasing references, expect 408 dots........................................................................................................................................................................................................................................................................................................................................................................................................................
Eliminating duplicate references........................................................................................................................................................................................................................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

jhat将启动一个http服务器,在浏览器中访问http://localhost:7000/

共提供了上面几个功能。

  • All classes including platform(显示所有类)

  • Show all members of the rootset (显示所有rootset)

  • Show instance counts for all classes (including platform)(显示所有类的示例数量,含JVM自身运行相关)

  • Show instance counts for all classes (excluding platform)(显示所有类的实例数量,不含JVM自身运行相关)

  • Show heap histogram (显示堆分布直方图)

  • Show finalizer summary

  • Execute Object Query Language (OQL) query(使用OQL查询)

其中,最常用到的。

(1)Show instance counts for all classes (excluding platform)

(2)Show heap histogram

 

1.7 jstack:Java堆栈跟踪工具

jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合。

生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。

$ jstack -help
Usage:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)
​
Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung) //强制
    -m  to print both java and native frames (mixed mode)       //如果调用到本地方法的话,可以显示c/c++的堆栈 
    -l  long listing. Prints additional information about locks //除堆栈外,还会显示锁的附加信息
    -h or -help to print this help message

jstack命令格式:

jstack [option] vmid

option选项:

-F : 当正常输出请求不被响应时,强制输出线程堆栈
-l : 除堆栈外,显示关于锁的附加信息
-m : 如果调用到本地方法的话,可以显示C/C++的堆栈

常用命令:

jstack -l <pid>

使用示例:

jstack不仅可以输出线程堆栈,还能自动进行死锁检查。

下面演示死锁的发生,线程分别占有lockA和lockB,然后请求对方的锁,导致死锁发生。

public class DeadLockDemo extends Thread {
​
    static ReentrantLock lockA = new ReentrantLock();
    static ReentrantLock lockB = new ReentrantLock();
​
    private Object myLock;
​
    public DeadLockDemo(Object myLock) {
        this.myLock = myLock;
        if (myLock == lockA) {
            this.setName("Thread-hold-lockA");
        }
        if (myLock == lockB) {
            this.setName("Thread-hold-lockB");
        }
    }
​
    @Override
    public void run() {
        if (myLock == lockA) {
            try {
                lockA.lockInterruptibly();//占有lockA
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
​
                }
                lockB.lockInterruptibly();//请求lockB
                System.out.println(Thread.currentThread().getName() + "成功获取到lockB");
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "获取lockB失败");
            } finally {
                if (lockA.isHeldByCurrentThread()) {
                    lockA.unlock();
                }
                if (lockB.isHeldByCurrentThread()) {
                    lockB.unlock();
                }
            }
        }
​
        if (myLock == lockB) {
            try {
                lockB.lockInterruptibly();//占有lockB
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
​
                }
                lockA.lockInterruptibly();//请求lockA
                System.out.println(Thread.currentThread().getName() + "成功获取到lockA");
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "获取lockA失败");
            } finally {
                if (lockA.isHeldByCurrentThread()) {
                    lockA.unlock();
                }
                if (lockB.isHeldByCurrentThread()) {
                    lockB.unlock();
                }
            }
        }
    }
​
    public static void main(String[] args) throws InterruptedException{
        DeadLockDemo hasLockA = new DeadLockDemo(lockA);
        DeadLockDemo hasLockB = new DeadLockDemo(lockB);
        hasLockA.start();
        hasLockB.start();
        Thread.sleep(100000);
    }
}

然后,dump出线程堆栈。

jstack -l 5665 > jstackout

jstackout文件内容如下:

2019-01-06 20:14:10
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode):
                    //是否是守护线程,
"Attach Listener" #12 daemon prio=9 os_prio=31 tid=0x00007f8070871000 nid=0x1407 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
​
   Locked ownable synchronizers:
        - None
 //线程名          prio是线程优先级          tid是线程id           nid是映射到操作系统的线程id  
"Thread-hold-lockB" #11 prio=5 os_prio=31 tid=0x00007f806f045800 nid=0x5903 waiting on condition [0x000070000857c000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000076abadef0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
        at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
        at com.thelight1.juc.DeadLockDemo.run(DeadLockDemo.java:57)
​
   Locked ownable synchronizers://持有的锁(如果不加-l参数,将不打印这部分内容)
        - <0x000000076abadf20> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
​
"Thread-hold-lockA" #10 prio=5 os_prio=31 tid=0x00007f806f044800 nid=0x5703 waiting on condition [0x0000700008479000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000076abadf20> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
        at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
        at com.thelight1.juc.DeadLockDemo.run(DeadLockDemo.java:35)
​
   Locked ownable synchronizers:
        - <0x000000076abadef0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
Found one Java-level deadlock: //发现死锁
=============================
"Thread-hold-lockB": //线程Thread-hold-lockB想要请求0x000000076abadef0,但是已经被Thread-hold-lockA占有了
  waiting for ownable synchronizer 0x000000076abadef0, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
  which is held by "Thread-hold-lockA"
"Thread-hold-lockA":
  waiting for ownable synchronizer 0x000000076abadf20, (a java.util.concurrent.locks.ReentrantLock$NonfairSync),
  which is held by "Thread-hold-lockB"
​
Java stack information for the threads listed above:
===================================================
"Thread-hold-lockB":
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000076abadef0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
        at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
        at com.thelight1.juc.DeadLockDemo.run(DeadLockDemo.java:57)
"Thread-hold-lockA":
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000076abadf20> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:897)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
        at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
        at com.thelight1.juc.DeadLockDemo.run(DeadLockDemo.java:35)
​
Found 1 deadlock.
posted @ 2019-01-20 17:43  Ye_yang  阅读(1383)  评论(0编辑  收藏  举报