JVM 性能调优工具讲解 jstat、jmap、jstack、jinfo

1、jstat


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

jstat 用法

$ 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.
  • option: 参数选项

  • -t: 可以在打印的列加上Timestamp列,用于显示系统运行的时间

  • -h: 可以在周期性数据数据的时候,可以在指定输出多少行以后输出一次表头

  • vmid: Virtual Machine ID( 进程的 pid)

  • interval: 执行每次的间隔时间,单位为毫秒

  • count: 用于指定输出多少次记录,缺省则会一直打印

$ jstat -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation

option 可以从下面参数中选择

  • -class 显示ClassLoad的相关信息;

  • -compiler 显示JIT编译的相关信息;

  • -gc 显示和gc相关的堆信息;

  • -gccapacity 显示各个代的容量以及使用情况;

  • -gcmetacapacity 显示metaspace的大小

  • -gcnew 显示新生代信息;

  • -gcnewcapacity 显示新生代大小和使用情况;

  • -gcold 显示老年代和永久代的信息;

  • -gcoldcapacity 显示老年代的大小;

  • -gcutil 显示垃圾收集信息;

  • -gccause 显示垃圾回收的相关信息(通-gcutil),同时显示最后一次或当前正在发生的垃圾回收的诱因;

  • -printcompilation 输出JIT编译的方法信息;

示例一:-class

显示加载class的数量,及所占空间等信息。

jstat -class <pid>
Loaded  Bytes  Unloaded  Bytes     Time
  3350  6358.6        9     9.0       2.14
  • Loaded : 已经装载的类的数量

  • Bytes : 装载类所占用的字节数

  • Unloaded:已经卸载类的数量

  • Bytes:卸载类的字节数

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

示例二:-compiler

显示VM实时编译(JIT)的数量等信息。

jstat -compiler <pid>
Compiled Failed Invalid   Time   FailedType FailedMethod
    1553      0       0     4.41          0
  • Compiled:编译任务执行数量

  • Failed:编译任务执行失败数量

  • Invalid :编译任务执行失效数量

  • Time :编译任务消耗时间

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

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

示例三:-gc

显示gc相关的堆信息,查看gc的次数,及时间。

jstat –gc <pid>
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
13312.0 13312.0  0.0    0.0   82432.0    0.0     120832.0   20495.1   19712.0 19399.0 2304.0 2230.7      3    0.063   2      0.153    0.217
13312.0 13312.0  0.0    0.0   82432.0    0.0     120832.0   20495.1   19712.0 19399.0 2304.0 2230.7      3    0.063   2      0.153    0.217
13312.0 13312.0  0.0    0.0   82432.0    0.0     120832.0   20495.1   19712.0 19399.0 2304.0 2230.7      3    0.063   2      0.153    0.217
13312.0 13312.0  0.0    0.0   82432.0    0.0     120832.0   20495.1   19712.0 19399.0 2304.0 2230.7      3    0.063   2      0.153    0.217
13312.0 13312.0  0.0    0.0   82432.0    0.0     120832.0   20495.1   19712.0 19399.0 2304.0 2230.7      3    0.063   2      0.153    0.217
13312.0 13312.0  0.0    0.0   82432.0    0.0     120832.0   20495.1   19712.0 19399.0 2304.0 2230.7      3    0.063   2      0.153    0.217
13312.0 13312.0  0.0    0.0   82432.0    0.0     120832.0   20495.1   19712.0 19399.0 2304.0 2230.7      3    0.063   2      0.153    0.217
  • S0C:年轻代中第一个survivor(幸存区)的容量 (字节)

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

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

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

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

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

  • OC :Old代的容量 (字节)

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

  • MC:metaspace(元空间)的容量 (字节)

  • MU:metaspace(元空间)目前已使用空间 (字节)

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

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

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

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

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

示例四:-gccapacity

可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小。

jstat -gccapacity <pid>
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
109056.0 238592.0 109056.0 13312.0 13312.0  82432.0   218624.0   478208.0   120832.0   120832.0      0.0 1067008.0  19712.0      0.0 1048576.0   2304.0      3     2
  • NGCMN :年轻代(young)中初始化(最小)的大小(字节)

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

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

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

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

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

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

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

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

  • OC :Old代的容量 (字节)

  • MCMN:metaspace(元空间)中初始化(最小)的大小 (字节)

  • MCMX :metaspace(元空间)的最大容量 (字节)

  • MC :metaspace(元空间)当前新生成的容量 (字节)

  • CCSMN:最小压缩类空间大小

  • CCSMX:最大压缩类空间大小

  • CCSC:当前压缩类空间大小

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

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

示例五:-gcmetacapacity

metaspace 中对象的信息及其占用量。

jstat -gcmetacapacity <pid>
   MCMN       MCMX        MC       CCSMN      CCSMX       CCSC     YGC   FGC    FGCT     GCT
       0.0  1067008.0    19712.0        0.0  1048576.0     2304.0     3     2    0.153    0.217
  • MCMN:最小元数据容量

  • MCMX:最大元数据容量

  • MC:当前元数据空间大小

  • CCSMN:最小压缩类空间大小

  • CCSMX:最大压缩类空间大小

  • CCSC:当前压缩类空间大小

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

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

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

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

示例六:-gcnew

年轻代对象的信息。

jstat -gcnew <pid>
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
13312.0 13312.0    0.0    0.0  7  15 13312.0  82432.0      0.0      3    0.063
  • S0C :年轻代中第一个survivor(幸存区)的容量 (字节)

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

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

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

  • TT:持有次数限制

  • MTT:最大持有次数限制

  • DSS:期望的幸存区大小

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

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

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

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

示例七:-gcnewcapacity

年轻代对象的信息及其占用量。

jstat -gcnewcapacity <pid>
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
  109056.0   238592.0   109056.0  79360.0  13312.0  79360.0  13312.0   237568.0    82432.0     3     2
  • NGCMN :年轻代(young)中初始化(最小)的大小(字节)

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

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

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

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

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

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

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

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

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

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

示例八:-gcold

old代对象的信息。

jstat -gcold <pid>
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT
 19712.0  19399.0   2304.0   2230.7    120832.0     20495.1      3     2    0.153    0.217
  • MC :metaspace(元空间)的容量 (字节)

  • MU:metaspace(元空间)目前已使用空间 (字节)

  • CCSC:压缩类空间大小

  • CCSU:压缩类空间使用大小

  • OC:Old代的容量 (字节)

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

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

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

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

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

示例九:-gcoldcapacity

old代对象的信息及其占用量。

jstat -gcoldcapacity <pid>
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT
   218624.0    478208.0    120832.0    120832.0     3     2    0.153    0.217
  • OGCMN :old代中初始化(最小)的大小 (字节)

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

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

  • OC :Old代的容量 (字节)

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

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

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

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

示例十:-gcutil

统计gc信息。

jstat -gcutil <pid>
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00   0.00  16.96  98.41  96.82      3    0.063     2    0.153    0.217
  • 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)

示例十一:-gccause

显示垃圾回收的相关信息(通-gcutil),同时显示最后一次或当前正在发生的垃圾回收的诱因。

jstat -gccause <pid>
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC
  0.00   0.00   0.00  16.96  98.41  96.82      3    0.063     2    0.153    0.217 Heap Inspection Initiated GC No GC
  • LGCC:最后一次GC原因

  • GCC:当前GC原因(No GC 为当前没有执行GC)

示例十二:-printcompilation

当前VM执行的信息。

jstat -printcompilation <pid>
Compiled  Size  Type Method    1553      5    1 java/util/zip/ZipFile$ZipFileInflaterInputStream finalize
  • Compiled :编译任务的数目

  • Size :方法生成的字节码的大小

  • Type:编译类型

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


2、jmap


摘要: Jmap命令是一个多功能的命令。它可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。

jmap 用法

$ jmap -help
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

参数

  • option: 选项参数。

  • pid: 需要打印配置信息的进程ID。

  • executable: 产生核心dump的Java可执行文件。

  • core: 需要打印配置信息的核心文件。

  • server-id 可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器。

  • remote server IP or hostname 远程调试服务器的IP地址或主机名。

option

  • no option: 查看进程的内存映像信息,类似 Solaris pmap 命令。

  • heap: 显示Java堆详细信息

  • histo[:live]: 显示堆中对象的统计信息

  • clstats:打印类加载器信息

  • finalizerinfo: 显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象

  • dump::生成堆转储快照

  • F: 当-dump没有响应时,使用-dump或者-histo参数. 在这个模式下,live子参数无效.

  • help:打印帮助信息

  • J:指定传递给运行jmap的JVM的参数

示例一:no option

查看进程的内存映像信息,类似 Solaris pmap 命令。

jmap <pid>

使用不带选项参数的jmap打印共享对象映射,将会打印目标虚拟机中加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。这与Solaris的pmap工具比较相似。

Attaching to process ID 4628, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12
0x000000006a280000      8828K   D:\Program Files\Java\jdk1.8.0_161\jre\bin\server\jvm.dll
0x000000006c1c0000      840K    D:\Program Files\Java\jdk1.8.0_161\jre\bin\msvcr100.dll
0x000000006c350000      68K     D:\Program Files\Java\jdk1.8.0_161\jre\bin\nio.dll
0x000000006c370000      104K    D:\Program Files\Java\jdk1.8.0_161\jre\bin\net.dll
0x000000006c390000      88K     D:\Program Files\Java\jdk1.8.0_161\jre\bin\zip.dll
0x000000006c3b0000      164K    D:\Program Files\Java\jdk1.8.0_161\jre\bin\java.dll
0x000000006c3e0000      60K     D:\Program Files\Java\jdk1.8.0_161\jre\bin\verify.dll
0x00007ff70beb0000      220K    D:\Program Files\Java\jdk1.8.0_161\bin\java.exe
0x00007ff98fea0000      36K     C:\WINDOWS\SYSTEM32\WSOCK32.dll

示例二:heap

显示Java堆详细信息。

jmap -heap <pid>

打印一个堆的摘要信息,包括使用的GC算法、堆配置信息和各内存区域内存使用信息。

Attaching to process ID 4628, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12

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

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 734003200 (700.0MB)
   NewSize                  = 111673344 (106.5MB)
   MaxNewSize               = 244318208 (233.0MB)
   OldSize                  = 223870976 (213.5MB)
   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 = 84410368 (80.5MB)
   used     = 0 (0.0MB)
   free     = 84410368 (80.5MB)
   0.0% used
From Space:
   capacity = 13631488 (13.0MB)
   used     = 0 (0.0MB)
   free     = 13631488 (13.0MB)
   0.0% used
To Space:
   capacity = 13631488 (13.0MB)
   used     = 0 (0.0MB)
   free     = 13631488 (13.0MB)
   0.0% used
PS Old Generation
   capacity = 123731968 (118.0MB)
   used     = 20986936 (20.01470184326172MB)
   free     = 102745032 (97.98529815673828MB)
   16.96161173157773% used

5082 interned Strings occupying 448296 bytes.

示例三:histo[:live]

显示堆中对象的统计信息。

jmap -histo:live <pid>

其中包括每个Java类、对象数量、内存大小(单位:字节)、完全限定的类名。打印的虚拟机内部的类名称将会带有一个’*’前缀。如果指定了live子选项,则只计算活动的对象。

 num     #instances         #bytes  class name----------------------------------------------
   1:           649       17000784  [B
   2:         15489        1462736  [C
   3:          3603         402048  java.lang.Class
   4:         15306         367344  java.lang.String
   5:          4232         363480  [Ljava.lang.Object;
   6:          6938         222016  java.util.concurrent.ConcurrentHashMap$Node
   7:          6447         103152  java.lang.Object
   8:          3026          96832  java.util.HashMap$Node
   9:          1418          68808  [I
  10:            47          58064  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  11:           788          37824  gnu.trove.THashMap
  12:           210          33792  [Ljava.util.HashMap$Node;
  13:           841          33640  java.util.TreeMap$Entry
  14:           434          27776  io.netty.buffer.PoolSubpage
  15:           530          21200  java.lang.ref.SoftReference

示例四:clstats

打印类加载器信息。

jmap -clstats <pid>

-clstats是-permstat的替代方案,在JDK8之前,-permstat用来打印类加载器的数据
打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印。

Attaching to process ID 4628, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness.............liveness analysis may be inaccurate ...
class_loader    classes bytes   parent_loader   alive?  type<bootstrap>     1436    2534882   null          live    <internal>
0x00000000d5414f20      2099    3484055 0x00000000d54398c8      live    java/net/URLClassLoader@0x000000010000ecd0
0x00000000d5751b60      0       0       0x00000000d54398c8      dead    java/util/ResourceBundle$RBClassLoader@0x0000000100093bc8
0x00000000d54398c8      25      101450  0x00000000d5439928      live    sun/misc/Launcher$AppClassLoader@0x000000010000f6a0
0x00000000d5439928      3       2574      null          live    sun/misc/Launcher$ExtClassLoader@0x000000010000fa48

total = 5       3563    6122961     N/A         alive=4, dead=1     N/A

示例五:finalizerinfo

打印等待终结的对象信息。

jmap -finalizerinfo <pid>
Attaching to process ID 4628, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12
Number of objects pending for finalization: 0

Number of objects pending for finalization: 0 说明当前F-QUEUE队列中并没有等待Fializer线程执行final

示例六:dump[:dump-options]

生成堆转储快照dump文件。

jmap -dump:format=b,file=heapdump.phrof <pid>

以hprof二进制格式转储Java堆到指定filename的文件中。live子选项是可选的。如果指定了live子选项,堆中只有活动的对象会被转储。想要浏览heap dump,你可以使用jhat(Java堆分析工具)读取生成的文件。

$ jmap -dump:format=b,file=heapdump.phrof 4628
Dumping heap to C:\Users\Victor.Zxy\heapdump.phrof ...
Heap dump file created

这个命令执行,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用, 线上系统慎用。


3、jstack


摘要: Jstack是jdk自带的线程堆栈分析工具,使用该命令可以查看或导出 Java 应用程序中线程堆栈信息。

Jstack 用法

$ 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)    -l  long listing. Prints additional information about locks
    -h or -help to print this help message

参数说明:

  • -l 长列表. 打印关于锁的附加信息,例如属于java.util.concurrent 的 ownable synchronizers列表

  • -F 当’jstack [-l] pid’没有相应的时候强制打印栈信息

  • -m 打印java和native c/c++框架的所有栈信息

  • -h | -help 打印帮助信息

  • pid 需要被打印配置信息的java进程id,可以用jps查询

Jstack 使用

通过使用 jps 命令获取需要监控的进程的pid,然后使用 jstack pid 命令查看线程的堆栈信息。

$ jstack 4628
2019-05-08 13:52:47
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.161-b12 mixed mode):"NettythreadDeathWatcher-2-1" #17 daemon prio=1 os_prio=-2 tid=0x0000000018473800 nid=0x5aa4 waiting on condition [0x000000001b9af000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at io.netty.util.ThreadDeathWatcher$Watcher.run(ThreadDeathWatcher.java:152)
        at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
        at java.lang.Thread.run(Thread.java:748)"DestroyJavaVM" #15 prio=5 os_prio=0 tid=0x0000000018476800 nid=0x2a28 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE"JPS event loop" #10 prio=5 os_prio=0 tid=0x00000000175d1000 nid=0x4cac runnable [0x0000000017b8f000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
        at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(WindowsSelectorImpl.java:296)
        at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(WindowsSelectorImpl.java:278)
        at sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:159)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        - locked <0x00000000d541b7c0> (a io.netty.channel.nio.SelectedSelectionKeySet)
        - locked <0x00000000d541b7b0> (a java.util.Collections$UnmodifiableSet)
        - locked <0x00000000d541b730> (a sun.nio.ch.WindowsSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
        at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:752)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
        at java.lang.Thread.run(Thread.java:748)

通过 jstack 命令可以获取当前进程的所有线程信息。
每个线程堆中信息中,都可以查看到 线程ID、线程的状态(wait、sleep、running 等状态)、是否持有锁信息等。

死锁示例

下面通过一个例子,来演示 jstack 检查死锁的一个例子,代码如下:

public static void deathLock() {
    Thread t1 = new Thread() {        @Override
        public void run() {            try {
                lock1.lock();
                TimeUnit.SECONDS.sleep(1);
                lock2.lock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    Thread t2 = new Thread() {        @Override
        public void run() {            try {
                lock2.lock();
                TimeUnit.SECONDS.sleep(1);
                lock1.lock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    t1.setName("mythread1");
    t2.setName("mythread2");
    t1.start();
    t2.start();
}

使用 jstack -l pid 查看线程堆栈信息,发现在堆栈信息最后面检查出了一个死锁。如下图

image

可以清楚的看出 mythread2 等待 这个锁 “0x00000000d6eb82d0”,这个锁是由于mythread1线程持有。
mythread1线程等待这个锁“0x00000000d6eb8300”,这个锁是由mythread2线程持有。

“mythread1”线程堆栈信息如下:

image

可以看出当前线程持有“0x00000000d6eb82d0”锁,等待“0x00000000d6eb8300”的锁

“mythread2”线程堆栈信息如下:

image

“mythread2”的堆栈信息中可以看出当前线程持有“0x00000000d6eb8300”锁,等待“0x00000000d6eb82d0”的锁。


4、 jps


摘要: Jps 命令类似与 linux 的 ps 命令,但是它只列出系统中所有的 Java 应用程序。 通过 jps 命令可以方便地查看 Java 进程的启动类、传入参数和 Java 虚拟机参数等信息。如果在 linux 中想查看 java 的进程,一般我们都需要 ps -ef | grep java 来获取进程 ID。

jps 用法

$ jps -help
usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

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

参数说明

  • -q:只输出进程 ID

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

  • -l:输出完全的包名,应用主类名,jar的完全路径名

  • -v:输出jvm参数

  • -V:输出通过flag文件传递到JVM中的参数

[hostid]:远程服务器地址,jps 支持远程调用
[protocol:][[//]hostname][:port][/servername]

示例一:jps

无参数:显示进程的ID 和 启动类的名称。

$ jps
22912 Launcher
22260
4628 Launcher
31112 Jps
34712 Launcher
27884 RemoteJdbcServer

示例二:jps -q

参数 -q 只输出进程ID,而不显示出类的名称。

$ jps -q
22912
37616
22260
4628
34712
27884

示例三:jps -m

参数 -m 可以输出传递给 Java 进程(main 方法)的参数。

$ jps -m
22912 Launcher D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jps-builders.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/annotations.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/trove4j.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/resources_en.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/protobuf-java-3.0.0.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/idea_rt.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/commons-logging-1.2.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/slf4j-api-1.7.10.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/asm-all.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/lz4-java-1.3.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/javac2.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/aether-1.1.0-all.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/httpcore-4.4.5.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/guava-21.0.jar;D:/Program Files/JetBra
22260
4628 Launcher D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jps-builders.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/annotations.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/trove4j.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/resources_en.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/protobuf-java-3.0.0.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/idea_rt.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/commons-logging-1.2.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/slf4j-api-1.7.10.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/asm-all.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/lz4-java-1.3.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/javac2.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/aether-1.1.0-all.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/httpcore-4.4.5.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/guava-21.0.jar;D:/Program Files/JetBra
34712 Launcher D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jps-builders.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/annotations.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/trove4j.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/resources_en.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/protobuf-java-3.0.0.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/idea_rt.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/commons-logging-1.2.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/slf4j-api-1.7.10.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/asm-all.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/lz4-java-1.3.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/javac2.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/aether-1.1.0-all.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/httpcore-4.4.5.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/guava-21.0.jar;D:/Program Files/JetBra
1484 Jps -m
27884 RemoteJdbcServer com.mysql.jdbc.Driver

示例四:jps -l

参数 -l 可以输出主函数的完整路径(类的全路径)。

$ jps -l22912 org.jetbrains.jps.cmdline.Launcher
22260
30628 sun.tools.jps.Jps
4628 org.jetbrains.jps.cmdline.Launcher
34712 org.jetbrains.jps.cmdline.Launcher
27884 com.intellij.database.remote.RemoteJdbcServer

示例五:jps -v

参数 -v 可以显示传递给 Java 虚拟机的参数。

$ jps -v
22912 Launcher -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=D:/WorkSpace/hqev/rbac -Dpreload.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/options -Dcompile.parallel=false -Drebuild.on.dependency.change=true -Djava.net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=8246017585702392224 -Dfile.encoding=UTF-8 -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2018.1 -Didea.home.path=D:\Program Files\JetBrains\IntelliJ IDEA 2018.1 -Didea.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config -Didea.plugins.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/plugins -Djps.log.dir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/log/build-log -Djps.fallback.jdk.home=D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/jre64 -Djps.fallback.jdk.version=1.8.0_152-release -Dio.netty.noUnsafe=true -Djava.io.tmpdir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/compile-server/rbac_aca57a50/_temp_ -D
22260  -Xms2048m -Xmx2048m -Xmn264m -XX:MaxPermSize=350m -XX:PermSize=128m -XX:ReservedCodeCacheSize=240m -XX:+UseCompressedOops -Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50 -ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -XX:MaxJavaStackTraceDepth=-1 -Xverify:none -XX:ErrorFile=$USER_HOME/java_error_in_idea_%p.log -XX:HeapDumpPath=$USER_HOME/java_error_in_idea.hprof -XX:+DisableAttachMechanism -Djb.vmOptionsFile=C:\Users\Victor.Zxy\.IntelliJIdea2018.1\config\idea64.exe.vmoptions -Didea.jre.check=true -Dide.native.launcher=true -Didea.paths.selector=IntelliJIdea2018.1 -XX:ErrorFile=C:\Users\Victor.Zxy\java_error_in_idea_%p.log -XX:HeapDumpPath=C:\Users\Victor.Zxy\java_error_in_idea.hprof
27412 Jps -Dapplication.home=D:\Program Files\Java\jdk1.8.0_161 -Xms8m
4628 Launcher -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=D:/WorkSpace/hqev/faw-common-log -Dpreload.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/options -Dcompile.parallel=false -Drebuild.on.dependency.change=true -Djava.net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=8246017585702392224 -Dfile.encoding=UTF-8 -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2018.1 -Didea.home.path=D:\Program Files\JetBrains\IntelliJ IDEA 2018.1 -Didea.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config -Didea.plugins.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/plugins -Djps.log.dir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/log/build-log -Djps.fallback.jdk.home=D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/jre64 -Djps.fallback.jdk.version=1.8.0_152-release -Dio.netty.noUnsafe=true -Djava.io.tmpdir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/compile-server/faw-common-lo
34712 Launcher -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=D:/WorkSpace/hqev/tsp -Dpreload.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/options -Dcompile.parallel=false -Drebuild.on.dependency.change=true -Djava.net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=8246017585702392224 -Dfile.encoding=UTF-8 -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2018.1 -Didea.home.path=D:\Program Files\JetBrains\IntelliJ IDEA 2018.1 -Didea.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config -Didea.plugins.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/plugins -Djps.log.dir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/log/build-log -Djps.fallback.jdk.home=D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/jre64 -Djps.fallback.jdk.version=1.8.0_152-release -Dio.netty.noUnsafe=true -Djava.io.tmpdir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/compile-server/tsp_4876f785/_temp_ -Djp
27884 RemoteJdbcServer -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=127.0.0.1 -Duser.timezone=UTC -Dfile.encoding=UTF-8

获取远程服务器 jps 信息

jps 支持查看远程服务上的 jvm 进程信息。如果需要查看其他机器上的 jvm 进程,需要在待查看机器上启动 jstatd 服务。

开启 jstatd 服务

启动 jstatd 服务,需要有足够的权限。 需要使用 Java 的安全策略分配相应的权限。

创建 jstatd.all.policy 策略文件。

grant codebase "file:${java.home}/../lib/tools.jar" {
    permission java.security.AllPermission;
};

启动 jstatd 服务器

jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=192.168.31.241
  • -J 参数是一个公共的参数,如 jps、 jstat 等命令都可以接收这个参数。 由于 jps、 jstat 命令本身也是 Java 应用程序, -J 参数可以为 jps 等命令本身设置 Java 虚拟机参数。

  • -Djava.security.policy:指定策略文件

  • -Djava.rmi.server.hostname:指定服务器的ip地址(可忽略)

默认情况下, jstatd 开启在 1099 端口上开启 RMI 服务器。
image

jps 原理

java程序在启动以后,会在java.io.tmpdir指定的目录下,就是临时文件夹里,生成一个类似于hsperfdata_User的文件夹,这个文件夹里(在Linux中为/tmp/hsperfdata_{userName}/),有几个文件,名字就是java进程的pid,因此列出当前运行的java进程,只是把这个目录里的文件名列一下而已。 至于系统的参数什么,就可以解析这几个文件获得。

window系统显示如下:
image
从文件中可以看出 1864、4296、12600 跟上面的 jps 命令输出的进程 ID 一致。

 

5、jinfo


摘要: Jinfo 是 JDK 自带的命令,可以用来查看正在运行的 java 应用程序的扩展参数,包括Java System属性和JVM命令行参数;也可以动态的修改正在运行的 JVM 一些参数。当系统崩溃时,jinfo可以从core文件里面知道崩溃的Java应用程序的配置信息。

jinfo 用法

$ jinfo -help
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

参数说明

  • pid 对应jvm的进程id

  • executable core 产生core dump文件

  • [server-id@]remote server IP or hostname 远程的ip或者hostname,server-id标记服务的唯一性id

option

  • no option 输出全部的参数和系统属性

  • -flag name 输出对应名称的参数

  • -flag [+|-]name 开启或者关闭对应名称的参数

  • -flag name=value 设定对应名称的参数

  • -flags 输出全部的参数

  • -sysprops 输出系统属性

Javacore 概述

Javacore,也可以称为“threaddump”或是“javadump”,它是 Java 提供的一种诊断特性,能够提供一份可读的当前运行的 JVM 中线程使用情况的快照。即在某个特定时刻,JVM 中有哪些线程在运行,每个线程执行到哪一个类,哪一个方法。
应用程序如果出现不可恢复的错误或是内存泄露,就会自动触发 Javacore 的生成。

示例一:no option

命令:jinfo <pid>
描述:输出当前 jvm 进程的全部参数和系统属性

$ jinfo 22912
Attaching to process ID 22912, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12
Java System Properties:

java.vendor = Oracle Corporation
preload.project.path = D:/WorkSpace/hqev/rbac
sun.java.launcher = SUN_STANDARD
idea.config.path = D:/Program Files/JetBrains/IntelliJIdeaConfig/config
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
sun.nio.ch.bugLevel =
idea.paths.selector = IntelliJIdea2018.1
kotlin.daemon.client.alive.path = "C:\Users\Victor.Zxy\AppData\Local\Temp\kotlin-idea-3229673183181290493-is-running"os.name = Windows 10

示例二:-flag name

命令:jinfo -flag name <pid>
描述:输出对应名称的参数

$ jinfo -flag PrintGC 22912
-XX:-PrintGC

$ jinfo -flag PrintGCDetails 22912
-XX:-PrintGCDetails

$ jinfo -flag PrintGCTimeStamps 22912
-XX:-PrintGCTimeStamps

使用该命令,可以查看指定的 jvm 参数的值。如:查看当前 jvm 进程是否开启打印 GC 日志。

示例三:-flag [+|-]name

命令:jinfo -flag [+|-]name <pid>
描述:开启或者关闭对应名称的参数

$ jinfo -flag +PrintGC 22912

$ jinfo -flag PrintGC 22912
-XX:+PrintGC

$ jinfo -flag -PrintGC 22912

$ jinfo -flag PrintGC 22912
-XX:-PrintGC

使用 jinfo 可以在不重启虚拟机的情况下,可以动态的修改 jvm 的参数。尤其在线上的环境特别有用。

示例四:-flag name=value

命令:jinfo -flag name=value <pid>
描述:修改指定参数的值(同示例三,但示例三主要是针对 boolean 值的参数设置的。如果是设置 value值,则需要使用 name=value 的形式)。

$ jinfo -flag HeapDumpPath 22912
-XX:HeapDumpPath=

$ jinfo -flag HeapDumpPath=C:\Users\Victor.Zxy\error.hprof 22912

$ jinfo -flag HeapDumpPath 22912
-XX:HeapDumpPath=C:\Users\Victor.Zxy\error.hprof

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

示例五:-flags

命令:jinfo -flags <pid>
描述:输出全部的参数

$ jinfo -flags 22912
Attaching to process ID 22912, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12
Non-default VM flags: -XX:CICompilerCount=3 -XX:HeapDumpPath=null -XX:InitialHeapSize=335544320 -XX:MaxHeapSize=734003200 -XX:MaxNewSize=244318208 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=111673344 -XX:OldSize=223870976 -XX:-PrintGC -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=D:/WorkSpace/hqev/rbac -Dpreload.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/options -Dcompile.parallel=false -Drebuild.on.dependency.change=true -Djava.net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=8246017585702392224 -Dfile.encoding=UTF-8 -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2018.1 -Didea.home.path=D:\Program Files\JetBrains\IntelliJ IDEA 2018.1 -Didea.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config -Didea.plugins.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/plugins -Djps.log.dir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/log/build-log -Djps.fallback.jdk.home=D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/jre64 -Djps.fallback.jdk.version=1.8.0_152-release -Dio.netty.noUnsafe=true -Djava.io.tmpdir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/compile-server/rbac_aca57a50/_temp_ -Djps.backward.ref.index.builder=true -Dkotlin.incremental.compilation=true -Dkotlin.daemon.enabled -Dkotlin.daemon.client.alive.path="C:\Users\Victor.Zxy\AppData\Local\Temp\kotlin-idea-3229673183181290493-is-running"

示例六:-sysprops

命令:jinfo -sysprops <pid>
描述:输出当前 jvm 进行的全部的系统属性

$ jinfo -sysprops 22912
Attaching to process ID 22912, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12
java.vendor = Oracle Corporation
preload.project.path = D:/WorkSpace/hqev/rbac
sun.java.launcher = SUN_STANDARD
idea.config.path = D:/Program Files/JetBrains/IntelliJIdeaConfig/config
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
sun.nio.ch.bugLevel =
idea.paths.selector = IntelliJIdea2018.1
kotlin.daemon.client.alive.path = "C:\Users\Victor.Zxy\AppData\Local\Temp\kotlin-idea-3229673183181290493-is-running"os.name = Windows 10
sun.boot.class.path = D:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;D:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;D:\Program Files\Java\jdk1.8.0_161\jre\lib\sunrsasign.jar;D:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;D:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;D:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;D:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;D:\Program Files\Java\jdk1.8.0_161\jre\classes
sun.desktop = windows
idea.plugins.path = D:/Program Files/JetBrains/IntelliJIdeaConfig/config/plugins
java.vm.specification.vendor = Oracle Corporation
java.runtime.version = 1.8.0_161-b12


6、jcmd


摘要: 在JDK1.7以后,新增了一个命令行工具 jcmd。他是一个多功能的工具,可以用它来导出堆、查看Java进程、导出线程信息、执行GC、还可以进行采样分析(jmc 工具的飞行记录器)。

jcmd 用法

$ jcmd -help
Usage: jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
   or: jcmd -l
   or: jcmd -h  command must be a valid jcmd command for the selected jvm.
  Use the command "help" to see which commands are available.
  If the pid is 0, commands will be sent to all Java processes.
  The main class argument will be used to match (either partially
  or fully) the class used to start Java.
  If no options are given, lists Java processes (same as -p).

  PerfCounter.print display the counters exposed by this process  -f  read and execute commands from the file  -l  list JVM processes on the local machine
  -h  this help

参数描述

  • pid:接收诊断命令请求的进程ID。

  • main class :接收诊断命令请求的进程的main类。匹配进程时,main类名称中包含指定子字符串的任何进程均是匹配的。如果多个正在运行的Java进程共享同一个main类,诊断命令请求将会发送到所有的这些进程中。

  • command:接收诊断命令请求的进程的main类。匹配进程时,main类名称中包含指定子字符串的任何进程均是匹配的。如果多个正在运行的Java进程共享同一个main类,诊断命令请求将会发送到所有的这些进程中。
    注意: 如果任何参数含有空格,你必须使用英文的单引号或双引号将其包围起来。 此外,你必须使用转义字符来转移参数中的单引号或双引号,以阻止操作系统shell处理这些引用标记。当然,你也可以在参数两侧加上单引号,然后在参数内使用双引号(或者,在参数两侧加上双引号,在参数中使用单引号)。

  • Perfcounter.print:打印目标Java进程上可用的性能计数器。性能计数器的列表可能会随着Java进程的不同而产生变化。

  • -f file:从文件file中读取命令,然后在目标Java进程上调用这些命令。在file中,每个命令必须写在单独的一行。以"#"开头的行会被忽略。当所有行的命令被调用完毕后,或者读取到含有stop关键字的命令,将会终止对file的处理。

  • -l:查看所有的进程列表信息。

  • -h:查看帮助信息。(同 -help)

查看进程 jcmd -l

命令:jcmd -l
描述:查看 当前机器上所有的 jvm 进程信息。

jcmd
jcmd -ljps -m

这三个命令的效果是一样的

查看性能统计

命令:jcmd <pid> PerfCounter.print
描述:查看指定进程的性能统计信息。

$ jcmd 22912 PerfCounter.print
22912:
java.ci.totalTime=45473763
java.cls.loadedClasses=3350
java.cls.sharedLoadedClasses=0
java.cls.sharedUnloadedClasses=0
java.cls.unloadedClasses=0
java.property.java.class.path="D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jps-launcher.jar;D:/Program Files/Java/jdk1.8.0_161/lib/tools.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/optimizedFileManager.jar"java.property.java.endorsed.dirs=""""java.property.java.ext.dirs="D:\Program Files\Java\jdk1.8.0_161\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext"java.property.java.home="D:\Program Files\Java\jdk1.8.0_161\jre"...

列出当前运行的 java 进程可以执行的操作

命令:jcmd <pid> help

$ jcmd 22912 help22912:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_localManagementAgent.start
GC.rotate_logThread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.versionhelp

查看具体命令的选项

如果想查看命令的选项,比如想查看 JFR.dump 命令选项,可以通过如下命令: jcmd <pid> help JFR.dump

$ jcmd 22912 help JFR.dump
22912:
JFR.dump
Copies contents of a JFR recording to file. Either the name or the recording id must be specified.

Impact: Low

Permission: java.lang.management.ManagementPermission(monitor)

Syntax : JFR.dump [options]

Options: (options must be specified using the <key> or <key>=<value> syntax)
        name : [optional] Recording name, e.g. \"My Recording\" (STRING, no default value)
        recording : [optional] Recording number, use JFR.check to list available recordings (JLONG, -1)
        filename :  Copy recording data to file, i.e \"C:\Users\user\My Recording.jfr\" (STRING, no default value)
        compress : [optional] GZip-compress "filename" destination (BOOLEAN, false)

JFR 相关命令

JFR 功能跟 jmc.exe 工具的飞行记录器的功能一样的。
要使用 JFR 相关的功能,必须使用 VM.unlock_commercial_features 参数取消锁定商业功能。

$ jcmd 22912 JFR.start
22912:
Java Flight Recorder not enabled.

Use VM.unlock_commercial_features to enable.

jmc.exe 显示的提示
image

  • 启动JFR
    执行命令:jcmd $PID JFR.start name=abc,duration=120s

  • Dump JFR
    等待至少duration(本文设定120s)后,执行命令:jcmd PID JFR.dump name=abc,duration=120s filename=abc.jfr(注意,文件名必须为.jfr后缀)

  • 检查JFR状态
    执行命令:jcmd $PID JFR.check name=abc,duration=120s

  • 停止JFR
    执行命令:jcmd $PID JFR.stop name=abc,duration=120s

  • JMC分析
    切回开发机器,下载步骤3中生成的abc.jfr,打开jmc,导入abc.jfr即可进行可视化分析

VM.uptime

命令:jcmd <pid> VM.uptime
描述:查看 JVM 的启动时长。

$ jcmd 22912 VM.uptime
22912:
266194.602 s

GC.class_histogram

命令:jcmd <pid> GC.class_histogram
描述:查看系统中类统计信息。

$ jcmd 22912 GC.class_histogram
22912:

 num     #instances         #bytes  class name----------------------------------------------
   1:           649       17000784  [B
   2:         19299        1799336  [C
   3:          7474         475320  [Ljava.lang.Object;
   4:         19116         458784  java.lang.String
   5:          3603         402048  java.lang.Class
   6:          6979         223328  java.util.concurrent.ConcurrentHashMap$Node
   7:          4405         140960  java.util.HashMap$Node
   8:          2372         113856  gnu.trove.THashMap
   9:          6447         103152  java.lang.Object
  10:          1428          98088  [I
  11:            47          58064  [Ljava.util.concurrent.ConcurrentHashMap$Node;

这里和jmap -histo pid的效果是一样的,可以查看每个类的实例数量和占用空间大小。

Thread.print

命令:jcmd <pid> Thread.print
描述:查看线程堆栈信息。

$ jcmd 22912 Thread.print
22912:
2019-05-13 13:23:42
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.161-b12 mixed mode):"NettythreadDeathWatcher-2-1" #17 daemon prio=1 os_prio=-2 tid=0x00000000178f0800 nid=0x8190 waiting on condition [0x0000000018faf000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at io.netty.util.ThreadDeathWatcher$Watcher.run(ThreadDeathWatcher.java:152)
        at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
        at java.lang.Thread.run(Thread.java:748)"DestroyJavaVM" #15 prio=5 os_prio=0 tid=0x00000000178f1800 nid=0x67d4 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE"JPS event loop" #10 prio=5 os_prio=0 tid=0x0000000016ab4800 nid=0x1a80 runnable [0x00000000170ae000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
        at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(WindowsSelectorImpl.java:296)
        at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(WindowsSelectorImpl.java:278)
        at sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:159)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        - locked <0x00000000d5419030> (a io.netty.channel.nio.SelectedSelectionKeySet)
        - locked <0x00000000d5419020> (a java.util.Collections$UnmodifiableSet)
        - locked <0x00000000d5418fa0> (a sun.nio.ch.WindowsSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
        at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:752)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
        at java.lang.Thread.run(Thread.java:748)

该命令同 jstack 命令。

GC.heap_dump

命令:jcmd <pid> GC.heap_dump FILE_NAME
描述:查看 JVM 的Heap Dump。

$ jcmd 22912 GC.heap_dump d:\dump.hprof
22912:
Heap dump file created

跟 jmap命令:jmap -dump:format=b,file=heapdump.phrof pid 效果一样。导出的 dump 文件,可以使用MAT 或者 Visual VM 等工具进行分析(如果只指定文件名,默认会生成在启动 JVM 的目录里)。

VM.system_properties

命令:jcmd <pid> VM.system_properties
描述:查看 JVM 的属性信息。

$ jcmd 22912 VM.system_properties
22912:#Mon May 13 13:28:38 CST 2019java.vendor=Oracle Corporation
preload.project.path=D\:/WorkSpace/hqev/rbac
sun.java.launcher=SUN_STANDARD
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
sun.nio.ch.bugLevel=
idea.config.path=D\:/Program Files/JetBrains/IntelliJIdeaConfig/config
idea.paths.selector=IntelliJIdea2018.1
kotlin.daemon.client.alive.path="C\:\\Users\\Victor.Zxy\\AppData\\Local\\Temp\\kotlin-idea-3229673183181290493-is-running"os.name=Windows 10
sun.boot.class.path=D\:\\Program Files\\Java\\jdk1.8.0_161\\jre\\lib\\resources.jar;D\:\\Program Files\\Java\\jdk1.8.0_161\\jre\\lib\\rt.jar;D\:\\Program Files\\Java\\jdk1.8.0_161\\jre\\lib\\sunrsasign.jar;D\:\\Program Files\\Java\\jdk1.8.0_161\\jre\\lib\\jsse.jar;D\:\\Program Files\\Java\\jdk1.8.0_161\\jre\\lib\\jce.jar;D\:\\Program Files\\Java\\jdk1.8.0_161\\jre\\lib\\charsets.jar;D\:\\Program Files\\Java\\jdk1.8.0_161\\jre\\lib\\jfr.jar;D\:\\Program Files\\Java\\jdk1.8.0_161\\jre\\classes
sun.desktop=windows
idea.plugins.path=D\:/Program Files/JetBrains/IntelliJIdeaConfig/config/plugins
java.vm.specification.vendor=Oracle Corporation
java.runtime.version=1.8.0_161-b12
io.netty.serviceThreadPrefix=Netty
user.name=Victor.Zxy
kotlin.incremental.compilation=trueidea.home.path=D\:\\Program Files\\JetBrains\\IntelliJ IDEA 2018.1
user.language=zh
jdt.compiler.useSingleThread=truesun.boot.library.path=D\:\\Program Files\\Java\\jdk1.8.0_161\\jre\\bin
java.version=1.8.0_161
user.timezone=Asia/Shanghai

VM.flags

命令:jcmd <pid> VM.flags
描述:查看 JVM 的启动参数。

$ jcmd 22912 VM.flags
22912:
-XX:CICompilerCount=3 -XX:InitialHeapSize=335544320 
-XX:MaxHeapSize=734003200 -XX:MaxNewSize=244318208 
-XX:MinHeapDeltaBytes=524288 -XX:NewSize=111673344 
-XX:OldSize=223870976 -XX:-PrintGC -XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps 
-XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC

VM.command_line

命令:jcmd <pid> VM.command_line
描述:查看 JVM 的启动命令行。

$ jcmd 22912 VM.command_line
22912:
VM Arguments:
jvm_args: -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=D:/WorkSpace/hqev/rbac -Dpreload.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/options -Dcompile.parallel=false -Drebuild.on.dependency.change=true -Djava.net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=8246017585702392224 -Dfile.encoding=UTF-8 -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2018.1 -Didea.home.path=D:\Program Files\JetBrains\IntelliJ IDEA 2018.1 -Didea.config.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config -Didea.plugins.path=D:/Program Files/JetBrains/IntelliJIdeaConfig/config/plugins -Djps.log.dir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/log/build-log -Djps.fallback.jdk.home=D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/jre64 -Djps.fallback.jdk.version=1.8.0_152-release -Dio.netty.noUnsafe=true -Djava.io.tmpdir=D:/Program Files/JetBrains/IntelliJIdeaConfig/system/compile-server/rbac_aca57a50/_temp_ -Djps.backward.ref.index.builder=true -Dkotlin.incremental.compilation=true -Dkotlin.daemon.enabled -Dkotlin.daemon.client.alive.path="C:\Users\Victor.Zxy\AppData\Local\Temp\kotlin-idea-3229673183181290493-is-running"java_command: org.jetbrains.jps.cmdline.Launcher D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jps-builders.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/annotations.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/trove4j.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/resources_en.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/protobuf-java-3.0.0.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/idea_rt.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/commons-logging-1.2.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/slf4j-api-1.7.10.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/asm-all.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/lz4-java-1.3.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/javac2.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/aether-1.1.0-all.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/httpcore-4.4.5.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/guava-21.0.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jna.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/oro-2.0.8.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jps-model.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jps-builders-6.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/util.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/nanoxml-2.2.3.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/httpclient-4.5.2.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jna-platform.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/forms_rt.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/aether-dependency-resolver.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jgoodies-forms.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/snappy-in-java-0.5.1.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/maven-aether-provider-3.3.9-all.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/commons-cod
java_class_path (initial): D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/jps-launcher.jar;D:/Program Files/Java/jdk1.8.0_161/lib/tools.jar;D:/Program Files/JetBrains/IntelliJ IDEA 2018.1/lib/optimizedFileManager.jar
Launcher Type: SUN_STANDARD

GC.run_finalization

命令:jcmd <pid> GC.run_finalization
描述: 对 JVM 执行 java.lang.System.runFinalization()

$ jcmd 22912 GC.run_finalization
22912:
Command executed successfully

执行一次finalization操作,相当于执行java.lang.System.runFinalization()

GC.run

命令:jcmd <pid> GC.run
描述:对 JVM 执行 java.lang.System.gc()

$ jcmd 22912 GC.run
22912:
Command executed successfully

告诉垃圾收集器打算进行垃圾收集,而垃圾收集器进不进行收集是不确定的。

PerfCounter.print

命令:jcmd <pid> PerfCounter.print
描述:查看 JVM 性能相关的参数。

$ jcmd 22912 PerfCounter.print
22912:
java.ci.totalTime=45606938
java.cls.loadedClasses=3363
java.cls.sharedLoadedClasses=0
java.cls.sharedUnloadedClasses=0
java.cls.unloadedClasses=9
...

VM.version

命令:jcmd <pid> VM.version
描述:查看目标jvm进程的版本信息。

$ jcmd 22912 VM.version
22912:
Java HotSpot(TM) 64-Bit Server VM version 25.161-b12
JDK 8.0_161


本文整理自云栖社区

打赏 支付宝打赏 微信打赏

如果文章对您有帮助,欢迎移至上方打赏按钮...

随手一点
  • 打酱油

    2人

  • 5人

  • 呵呵

    2人

  • 草泥马

    1人

文章评论 抢沙发