JDK 自带 JVM 分析工具详解

本文基于 JDK 中自带的 JVM 工具来讲解,内容有

  • JDK 自带哪些 JVM 分析工具
  • 每个工具的具体使用场景


JDK 中自带的工具

目前,针对 Java 应用在运行过程中出现的大部分 JVM 问题(如 OOM,FGC 等),我们都可通过 JDK 中自带的一些工具来分析解决。JDK 自带的工具可在 JDK 的安装目录的 bin 文件夹下找到。见图 1。
在这里插入图片描述

图 1

在图 1 众多的命令中,几个常用命令需特别熟悉

  • jps
  • jinfo
  • jstack
  • jmap
  • jstat
  • jhat

以及不是 jdk 自带的 VisualVM。每个命令具体使用见下文。


使用技巧

每个工具都设置了若干选项,用于查看不同层面的信息,若不清楚每个工具应该配置什么参数,可通过

> cmd -help

来查看命令的使用方式,如查看 jps 使用方式。

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

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

当使用 jps 不带任何可选参数时,将返回 pid(进程号)及进程名称。
在这里插入图片描述

图 2

当仅使用 -q 参数时,将只返回 pid。
在这里插入图片描述

图 3


各工具使用场景

jps

jps 用于查看当前 JVM 上运行的 Java 进程。使用过 Linux 的同学都知道,Linux 系统下有一个 ps 命令,用于列出系统的所有进程,可配合不同的参数选项,查看不同层面的信息。jps 具体的使用方式可见图 2、图 3,此处不累述。

jinfo

jinfo 全称 Java Configuration info 可用于查看或设置(部分可动态配置的)

  • 具体的 pid 信息
  • 可执行文件信息
  • 远程服务信息

其使用方式如下

> 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

在这里,我们仅需知道 如何使用 jinfo 查看指定 pid 的信息 即可。
使用方式有以下三种

  • 仅使用 -flag(s) 可选参数
    使用 -flags 查看所有 VM 参数信息

    > jinfo -flags pid	
    

    在这里插入图片描述

    图 4

    或使用 -flag name 查看指定 name 的参数信息。(其实使用 -flags 已经可查看所有的 VM 参数,个人觉得没有特别大的必要使用 -flag 那么 查看单个 VM 参数信息)

    > jinfo -flag name pid
    
  • 仅使用 -sysprops 可选参数
    使用 -sysprops 参数查看系统信息,系统信息较多,这里不展示结果,感兴趣的同学可以自己在命令行输入下述命令查看。

    > jinfo -sysprops pid
    
  • 不使用任何可选参数

    > jinfo pid
    

    不使用任何参数查看进程信息时,将返回 -flags 和 -sysprops 两个参数的全部信息。

从图 4 可知,使用 jinfo 可查看到的 VM 参数信息有

  • 初始堆大小 InitialHeapSize
  • 最大堆大小 MaxHeapSize
  • 最大新生代大小 MaxNewSize
  • 老年代大小 OldSize
  • 垃圾回收算法 +UseParallelGC

jmap

jmap 用于查看指定 pid 进程内存相关的信息。与 jinfo 类似,我们仅关注与具体进程相关的信息,不关注具体文件或远程服务的信息。

> 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

当使用命令

> jmap -heap pid 

查看指定进程 id 内存信息时,将输出当前进程的堆内存概览,新生代、老年代的使用情况以及垃圾回收算法。如

> jmap -heap 2060
Attaching to process ID 2060, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.311-b11

using thread-local object allocation.
Parallel GC with 13 thread(s)     // 垃圾回收算法

Heap Configuration:    // 堆配置总览
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 10485760 (10.0MB)   // 堆大小
   NewSize                  = 3145728 (3.0MB)   // 新生代大小
   MaxNewSize               = 3145728 (3.0MB)    // 新生代最大值
   OldSize                  = 7340032 (7.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 = 2097152 (2.0MB)
   used     = 1416072 (1.3504714965820312MB)
   free     = 681080 (0.6495285034179688MB)
   67.52357482910156% used
From Space:   
   capacity = 524288 (0.5MB)
   used     = 516112 (0.4922027587890625MB)
   free     = 8176 (0.0077972412109375MB)
   98.4405517578125% used
To Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
PS Old Generation
   capacity = 7340032 (7.0MB)
   used     = 391312 (0.3731842041015625MB)
   free     = 6948720 (6.6268157958984375MB)
   5.331202915736607% used

若想看指定进程 id 下有多少对象正在等待被回收,可使用命令

> jmap -finalizerinfo pid

如当前进程无正在等待被回收对象时,将输出

> jmap -finalizerinfo 3932
Attaching to process ID 3932, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.311-b11
Number of objects pending for finalization: 0

使用 -histo[:live] 可查看每个 class 的实例数目,内存使用情以及类全名信息。如在 -histo 后加上 live 子参数,将只统计活的对象数量(即在统计之前会触发一次 Full GC)。如

> jmap -histo -F 3932
Attaching to process ID 3932, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.311-b11
Iterating over heap. This may take a while...
Object Histogram:

num       #instances    #bytes  Class description
--------------------------------------------------------------------------
1:              1441    1092752 byte[]
2:              5234    684472  char[]
3:              243     121520  int[]
4:              4251    102024  java.lang.String
5:              565     64944   java.lang.Class
6:              669     40048   java.lang.Object[]
7:              791     31640   java.util.TreeMap$Entry
...
// 以下还有很多,此处仅做 case 说明,未给出所有 class 的实例数量及相关信息

注意!!!

遍历堆并生成直方图的过程中,目标 JVM 都是 stop-the-world 的,所以对于较大的堆或者生产环境上的程序,要谨慎执行。如果目标 JVM 无响应,就加上 -F 参数强制执行之(同 jstack),此时 :live 开关无效化

若想把整个堆转存为快照文件,可使用 -dump 参数,如

> jmap -F -dump:file=3932.hprof 23308
Attaching to process ID 23308, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.311-b11
Dumping heap to 3932.hprof ...
Heap dump file created

生成快照文件可使用 jhat、VisualVM 等工具查看。

  • 使用 jhat 查看时会在本地启动一个服务监听 7000端口,直接访问 localhost:7000 可查看快照信息。
  • 使用 VisualVM 查看时,需先安装 VisualVM 插件,可戳下载

使用 VisualVM 查看效果如下。
在这里插入图片描述

图 5

jstack

jstack 与 jmap 类似,可查看或 dump 指定进程的内存信息,除此之外,jstack 还可分析前进程内各个线程的信息,如

  • 是否发生死锁
  • 线程执行耗时长的原因
  • 线程状态

等信息。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

需要说明的是,jstack 若查看的是 hung(挂起)的进程,需要使用 -F 强制输出,否则看不到任何输出信息。

在这里插入图片描述

图 6

jhat

jhat 可用于分析 dump 下来的二进制文件

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"

可根据具体需要,使用不同的参数分析 dump 下课来的文件,如

在这里插入图片描述

图 7

jstat

jstat 用于查看 jvm 内存回收统计信息,使用方式

> 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.

乍一看,好像没有看到啥有用参数,其实使用 jstat -options 可查看更多信息。

> jstat -options
-class             // 显示类加载信息
-compiler          // 显示编译信息
-gc                // 显示GC相关信息
-gccapacity        // 显示各区域容量及使用情况
-gccause           // 显示垃圾回收信息
-gcmetacapacity    // 显示元空间容量信息
-gcnew             // 显示新生代信息
-gcnewcapacity     // 显示新生代容量信息
-gcold             // 显示老年代信息
-gcoldcapacity     // 显示老年代容量信息
-gcutil            // 显示垃圾收集信息
-printcompilation  // 显示JIT编译的方法信息

如使用

> jstat -gc pid 2s 5

查看指定 pid 的 Java 进程内存回收信息,每隔 2s 输出一次,共输出 5 次,将得到

> jstat -gc 4280 2s 5
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
43520.0 43520.0  0.0    0.0   261120.0 157493.1  441856.0   13949.7   21296.0 20552.0 2944.0 2735.4      1    0.009   1      0.017    0.026
43520.0 43520.0  0.0    0.0   261120.0 157493.1  441856.0   13949.7   21296.0 20552.0 2944.0 2735.4      1    0.009   1      0.017    0.026
43520.0 43520.0  0.0    0.0   261120.0 157493.1  441856.0   13949.7   21296.0 20552.0 2944.0 2735.4      1    0.009   1      0.017    0.026
43520.0 43520.0  0.0    0.0   261120.0 157493.1  441856.0   13949.7   21296.0 20552.0 2944.0 2735.4      1    0.009   1      0.017    0.026
43520.0 43520.0  0.0    0.0   261120.0 157493.1  441856.0   13949.7   21296.0 20552.0 2944.0 2735.4      1    0.009   1      0.017    0.026

输出的信息中,各参数描述见下表。

参数描述
S0C年轻代中第一个survivor(幸存区)的容量 (字节)
S1C年轻代中第二个survivor(幸存区)的容量 (字节)
S0U年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC年轻代中Eden(伊甸园)的容量 (字节)
EU年轻代中Eden(伊甸园)目前已使用空间 (字节)
OCOld代的容量 (字节)
OUOld代目前已使用空间 (字节)
PCPerm(持久代)的容量 (字节)
PUPerm(持久代)目前已使用空间 (字节)
YGC从应用程序启动到采样时年轻代中gc次数
YGCT从应用程序启动到采样时年轻代中gc所用时间(s)
FGC从应用程序启动到采样时old代(全gc)gc次数
FGCT从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT从应用程序启动到采样时gc用的总时间(s)
表 1
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值