在《深入理解 java 虚拟机》学习的第四章,Java 虚拟机自身为我们提供了多种虚拟机性能监控与故障处理工具,这里做一下记录,方便以后查阅。

参考官方文档:JDK Tools and Utilities

# 如何查看一个 java 虚拟机进程,可以使用 ps 查,如下

[root@yjyapp ~]# ps -elf|grep java
0 S root      5816     1  0  80   0 - 2071759 futex_ Nov09 ?      04:29:00 /home/jdk1.7/jdk1.7.0_80/bin/java -Djava.util.logging.config.file=/app/tomcat_gps/apache-tomcat-7.0.79/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/app/tomcat_gps/apache-tomcat-7.0.79/endorsed -classpath /app/tomcat_gps/apache-tomcat-7.0.79/bin/bootstrap.jar:/app/tomcat_gps/apache-tomcat-7.0.79/bin/tomcat-juli.jar -Dcatalina.base=/app/tomcat_gps/apache-tomcat-7.0.79 -Dcatalina.home=/app/tomcat_gps/apache-tomcat-7.0.79 -Djava.io.tmpdir=/app/tomcat_gps/apache-tomcat-7.0.79/temp org.apache.catalina.startup.Bootstrap start
0 S root     21712 19844  0  80   0 - 25816 pipe_w 10:19 pts/0    00:00:00 grep java
0 S root     28431     1  0  80   0 - 1771037 futex_ Nov10 ?      01:58:39 /home/jdk1.7/jdk1.7.0_80/bin/java -Djava.util.logging.config.file=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server -Xms2048M -Xmx2048M -XX:PermSize=512M -XX:MaxPermSize=512M -Xss256k -XX:MaxTenuringThreshold=20 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=2 -XX:SoftRefLRUPolicyMSPerMB=0 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/endorsed -classpath /usr/local/tomcat-performance-test/apache-tomcat-7.0.79/bin/bootstrap.jar:/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79 -Dcatalina.home=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79 -Djava.io.tmpdir=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/temp org.apache.catalina.startup.Bootstrap start
[root@yjyapp ~]#

或者使用 jps 查寻

[root@yjyapp ~]# jps -v
22161 Jps -Denv.class.path=.:/home/jdk1.7/jdk1.7.0_80/lib/dt.jar:/home/jdk1.7/jdk1.7.0_80/lib/tools.jar -Dapplication.home=/home/jdk1.7/jdk1.7.0_80 -Xms8m
28431 Bootstrap -Djava.util.logging.config.file=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms2048M -Xmx2048M -XX:PermSize=512M -XX:MaxPermSize=512M -Xss256k -XX:MaxTenuringThreshold=20 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=2 -XX:SoftRefLRUPolicyMSPerMB=0 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/endorsed -Dcatalina.base=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79 -Dcatalina.home=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79 -Djava.io.tmpdir=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/temp
5816 Bootstrap -Djava.util.logging.config.file=/app/tomcat_gps/apache-tomcat-7.0.79/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/app/tomcat_gps/apache-tomcat-7.0.79/endorsed -Dcatalina.base=/app/tomcat_gps/apache-tomcat-7.0.79 -Dcatalina.home=/app/tomcat_gps/apache-tomcat-7.0.79 -Djava.io.tmpdir=/app/tomcat_gps/apache-tomcat-7.0.79/temp
[root@yjyapp ~]#

由于 jps 并不像 ps 使用应用程序名来查询进程,所以它查找所有的 Java 应用程序,包括即使没有使用 java 执行体的那种(注:jps 仅查找当前用户的 Java 进程)

下面我们针对某个进程来使用 jdk 监测工具

# jps 虚拟机进程状况工具

参考:官方文档

# jps -m

输出虚拟机进程启动时传递给主类 main()函数的参数

[root@yjyapp ~]# jps -m
22544 Jps -m
28431 Bootstrap start
5816 Bootstrap start
[root@yjyapp ~]#

# jps -l

输出主类的全名,如果进程执行的是 jar 包,输出 jar 路径

[root@yjyapp ~]# jps -l
23002 sun.tools.jps.Jps
28431 org.apache.catalina.startup.Bootstrap
5816 org.apache.catalina.startup.Bootstrap
[root@yjyapp ~]#

# jps -v

输出虚拟机进程启动时 jvm 参数

[root@yjyapp ~]# jps -v
23094 Jps -Denv.class.path=.:/home/jdk1.7/jdk1.7.0_80/lib/dt.jar:/home/jdk1.7/jdk1.7.0_80/lib/tools.jar -Dapplication.home=/home/jdk1.7/jdk1.7.0_80 -Xms8m
28431 Bootstrap -Djava.util.logging.config.file=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms2048M -Xmx2048M -XX:PermSize=512M -XX:MaxPermSize=512M -Xss256k -XX:MaxTenuringThreshold=20 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=2 -XX:SoftRefLRUPolicyMSPerMB=0 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/endorsed -Dcatalina.base=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79 -Dcatalina.home=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79 -Djava.io.tmpdir=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/temp
5816 Bootstrap -Djava.util.logging.config.file=/app/tomcat_gps/apache-tomcat-7.0.79/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/app/tomcat_gps/apache-tomcat-7.0.79/endorsed -Dcatalina.base=/app/tomcat_gps/apache-tomcat-7.0.79 -Dcatalina.home=/app/tomcat_gps/apache-tomcat-7.0.79 -Djava.io.tmpdir=/app/tomcat_gps/apache-tomcat-7.0.79/temp
[root@yjyapp ~]#

# jps -q

只输出 LVMID,省略主类的名称

[root@yjyapp ~]# jps -q
23157
28431
5816
[root@yjyapp ~]#

# jps -V

(注意这里是大写的 V)输出 LVMID,及主类的名称

[root@yjyapp ~]# jps -V
23276 Jps
28431 Bootstrap
5816 Bootstrap
[root@yjyapp ~]#

# jps

可以直接输入 jps,效果同(5)

[root@yjyapp ~]# jps
23561 Jps
28431 Bootstrap
5816 Bootstrap
[root@yjyapp ~]#

# jstat 虚拟机统计信息监视工具

参考:官方文档

# jstat -class pid

显示加载 class 的数量,及所占空间等信息。(pid 以 28431 为例)

[root@yjyapp ~]# jstat -class 28431
Loaded  Bytes  Unloaded  Bytes     Time   
  7928 16097.5        0     0.0       8.23
[root@yjyapp ~]#

# jstat -compiler pid

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

[root@yjyapp ~]# jstat -compiler 28431
Compiled Failed Invalid   Time   FailedType FailedMethod
    2121      1       0    30.13          1 java/lang/ClassLoader getClassLoadingLock
[root@yjyapp ~]#

# jstat -gc pid

可以显示 gc 的信息,查看 gc 的次数,及时间。其中最后五项,分别是 young gc 的次数,young gc 的时间,full gc 的次数,full gc 的时间,gc 的总时间。

[root@yjyapp ~]# jstat -gc 28431
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT   
68096.0 68096.0  0.0   7433.1 545344.0 232442.6 1415616.0   94136.2   524288.0 48490.8     57    3.055   0      0.000    3.055
[root@yjyapp ~]#

# jstat -gccapacity pid

可以显示,VM 内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN 显示的是最小 perm 的内存使用量,PGCMX 显示的是 perm 的内存最大使用量,PGC 是当前新生成的 perm 内存占用量,PC 是但前 perm 内存占用量。其他的可以根据这个类推, OC 是 old 内纯的占用量。

[root@yjyapp ~]# jstat -gccapacity 28431
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC 
681536.0 681536.0 681536.0 68096.0 68096.0 545344.0  1415616.0  1415616.0  1415616.0  1415616.0 524288.0 524288.0 524288.0 524288.0     57     0
[root@yjyapp ~]#

# jstat -gccause pid

统计 gc 信息统计。

[root@yjyapp ~]# jstat -gccause 28431
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC                 
  0.00  10.92  42.62   6.65   9.25     57    3.055     0    0.000    3.055 Allocation Failure   No GC               
[root@yjyapp ~]#

# jstat -gcnew pid

new 对象的信息。

[root@yjyapp ~]# jstat -gcnew 28431
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
68096.0 68096.0    0.0 7433.1 16  20 34048.0 545344.0 232442.6     57    3.055
[root@yjyapp ~]#

# jstat -gcnewcapacity pid

new 对象的信息及其占用量。

[root@yjyapp ~]# jstat -gcnewcapacity 28431
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC 
  681536.0   681536.0   681536.0  68096.0  68096.0  68096.0  68096.0   545344.0   545344.0    57     0
[root@yjyapp ~]#

# jstat -gcold pid

老年代信息统计

[root@yjyapp ~]# jstat -gcold 28431
   PC       PU        OC          OU       YGC    FGC    FGCT     GCT   
524288.0  48490.8   1415616.0     94136.2     57     0    0.000    3.055
[root@yjyapp ~]#

# jstat -gcoldcapacity pid

老年代占用等信息统计

[root@yjyapp ~]# jstat -gcoldcapacity 28431
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT   
  1415616.0   1415616.0   1415616.0   1415616.0    57     0    0.000    3.055
[root@yjyapp ~]#

# jstat -gcpermcapacity pid

perm 对象的信息及其占用量。

[root@yjyapp ~]# jstat -gcpermcapacity 28431
  PGCMN      PGCMX       PGC         PC      YGC   FGC    FGCT     GCT   
  524288.0   524288.0   524288.0   524288.0    57     0    0.000    3.055
[root@yjyapp ~]#

# jstat -gcutil pid

同(5)

[root@yjyapp ~]# jstat -gcutil 28431
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT   
  0.00  10.92  42.62   6.65   9.25     57    3.055     0    0.000    3.055
[root@yjyapp ~]#

# jstat -printcompilation pid

当前 VM 执行的信息。

[root@yjyapp ~]# jstat -printcompilation 28431
Compiled  Size  Type Method
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
[root@yjyapp ~]#

说明:上面的命令还可以在结尾添加两个参数,如下:表示每 250 毫秒打印一次,一共打印 6 次

[root@yjyapp ~]# jstat -printcompilation 28431 250 6
Compiled  Size  Type Method
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
[root@yjyapp ~]#

上面的命令还可以加一个参数 - h3,意思是每 3 行打印一下标题,如下

[root@yjyapp ~]# jstat -printcompilation -h3 28431 250 6
Compiled  Size  Type Method
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
Compiled  Size  Type Method
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
    2121   1050    1 sun/net/spi/DefaultProxySelector$2 run
[root@yjyapp ~]#

# jinfo 配置信息工具

参考:官方文档

# jinfo -flag MaxPermSize pid

Java 配置信息。配置信息包括 Java 系统属性和 JVM 命令行标志。能输出并修改运行时的 java 进程的运行参数

[root@yjyapp ~]#  jinfo -flag MaxPermSize 28431
-XX:MaxPermSize=536870912
[root@yjyapp ~]#

# jmap 内存映像工具

参考:官方文档
参考:cn blog

# jmap -histo pid

打印堆的直方图。对于每个 Java 类,将打印对象数量,以字节为单位的内存大小以及完全限定的类名称。 VM 内部类名称以 “*” 前缀打印。

[root@yjyapp ~]# jmap -histo 28431
... ...
3479:             1             16  org.apache.xpath.objects.XMLStringFactoryImpl
3480:             1             16  org.apache.ibatis.ognl.ObjectNullHandler
3481:             1             16  sun.text.normalizer.NormalizerBase$NFCMode
3482:             1             16  java.util.regex.Pattern$CharPropertyNames$19
3483:             1             16  org.apache.log4j.helpers.AppenderAttachableImpl
3484:             1             16  com.google.gson.internal.bind.TypeAdapters$1
Total       4460009      417507696

# jmap -heap pid

打印堆汇总信息

[root@yjyapp ~]# jmap -heap 28431
Attaching to process ID 28431, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.80-b11
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          = 697892864 (665.5625MB)
   MaxNewSize       = 697892864 (665.5625MB)
   OldSize          = 1395851264 (1331.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 536870912 (512.0MB)
   MaxPermSize      = 536870912 (512.0MB)
   G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 628162560 (599.0625MB)
   used     = 281853872 (268.7967987060547MB)
   free     = 346308688 (330.2657012939453MB)
   44.86957516220005% used
Eden Space:
   capacity = 558432256 (532.5625MB)
   used     = 274242344 (261.53787994384766MB)
   free     = 284189912 (271.02462005615234MB)
   49.10933081917102% used
From Space:
   capacity = 69730304 (66.5MB)
   used     = 7611528 (7.258918762207031MB)
   free     = 62118776 (59.24108123779297MB)
   10.915667311589521% used
To Space:
   capacity = 69730304 (66.5MB)
   used     = 0 (0.0MB)
   free     = 69730304 (66.5MB)
   0.0% used
concurrent mark-sweep generation:
   capacity = 1449590784 (1382.4375MB)
   used     = 96395424 (91.92984008789062MB)
   free     = 1353195360 (1290.5076599121094MB)
   6.649836979096026% used
Perm Generation:
   capacity = 536870912 (512.0MB)
   used     = 49654592 (47.35430908203125MB)
   free     = 487216320 (464.64569091796875MB)
   9.248888492584229% used
26066 interned Strings occupying 2995456 bytes.
[root@yjyapp ~]#

# jmap -permstat pid

打印 Java 堆永久生成的类加载器智能统计信息。对于每个类加载器,都会打印其名称,活性,地址,父类加载器以及它所加载的类的数量和大小。

[root@yjyapp ~]# jmap -permstat 28431
Attaching to process ID 28431, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.80-b11
finding class loader instances ..
...  ...

# jmap -dump:format=b,file=fileName pid

fileName 为 dump 出的文件名字,你自己定义,如下面的 String 文件

[root@yjyapp jalen]# jmap -dump:format=b,file=String 28431
Dumping heap to /home/jalen/String ...
Heap dump file created
[root@yjyapp jalen]# ls
apache-tomcat-7.0.81.tar.gz  catalina.jar  iftop-0.17.tar.gz  META-INF  org  String

# jconsoleGUI 程序

参考:

官方文档

官方文档 2

# jconsole pid

jconsole 是一个用 java 写的 GUI 程序,用来监控 VM,并可监控远程的 VM

# jstack 堆栈跟踪工具

参考:官方文档

# jhat 虚拟机堆转储快照分析工具

参考:未找到,似乎被移除了

# jsadebugd 调试工具

# 附录:

  1. 如果我们想要查服务器都启动了哪些 tomcat,可以使用如下 ps 查寻,如下,共启动了两个 tomcat 进程
[root@yjyapp ~]# ps -elf|grep tomcat
0 S root      5816     1  0  80   0 - 2071759 futex_ Nov09 ?      04:29:02 /home/jdk1.7/jdk1.7.0_80/bin/java -Djava.util.logging.config.file=/app/tomcat_gps/apache-tomcat-7.0.79/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/app/tomcat_gps/apache-tomcat-7.0.79/endorsed -classpath /app/tomcat_gps/apache-tomcat-7.0.79/bin/bootstrap.jar:/app/tomcat_gps/apache-tomcat-7.0.79/bin/tomcat-juli.jar -Dcatalina.base=/app/tomcat_gps/apache-tomcat-7.0.79 -Dcatalina.home=/app/tomcat_gps/apache-tomcat-7.0.79 -Djava.io.tmpdir=/app/tomcat_gps/apache-tomcat-7.0.79/temp org.apache.catalina.startup.Bootstrap start
0 S root     21915 19844  0  80   0 - 25816 pipe_w 10:22 pts/0    00:00:00 grep tomcat
0 S root     28431     1  0  80   0 - 1771037 futex_ Nov10 ?      01:58:40 /home/jdk1.7/jdk1.7.0_80/bin/java -Djava.util.logging.config.file=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server -Xms2048M -Xmx2048M -XX:PermSize=512M -XX:MaxPermSize=512M -Xss256k -XX:MaxTenuringThreshold=20 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=2 -XX:SoftRefLRUPolicyMSPerMB=0 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/endorsed -classpath /usr/local/tomcat-performance-test/apache-tomcat-7.0.79/bin/bootstrap.jar:/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79 -Dcatalina.home=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79 -Djava.io.tmpdir=/usr/local/tomcat-performance-test/apache-tomcat-7.0.79/temp org.apache.catalina.startup.Bootstrap start
[root@yjyapp ~]#
  1. 如果我们想要查询端口为 8080 的 tomcat 的 pid,可以使用 netstat 查询,如下可以看到其进程为 5816
[root@yjyapp ~]# netstat -ntulp|grep 8080
tcp        0      0 :::8080                     :::*                        LISTEN      5816/java
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Jalen Chu 微信支付

微信支付

Jalen Chu 支付宝

支付宝

Jalen Chu 公众号

公众号