在JDK/bin目录下有很多.exe文件,这些都是JDK提供给开发人员的一些监视虚拟机状态和故障处理的工具。什么?你不知道还有exe工具?那java.exe和javac.exe 一定不会陌生吧,没错,这些命令行都是jdk官方提供给开发者的jdk/lib/tools.jar类库的一层包装,一般面试都会问一些生产环境JVM故障是怎么定位处理的相关问题,那我们逐个击破来一一试用下这些工具的功能。
它的功能有些和UNIX的ps命令类似:可以列出正在运行的虚拟机进程,不同的是ps是列出系统的所有进程,而jps列出的只是java的虚拟机进程,并且会显示虚拟机运行主类(Main Class,main函数所在的类)名称以及这些进程的本地虚拟机唯一ID(LVMID,Local Virtual Machine Identifier),相对于JVM其他工具,这个工具的特点就是不需要指定LVMID来确定是哪一个虚拟机进程,类似于业务系统中的list接口,就是提供一个java虚拟机进程的列表。
对于本地虚拟机来说,LVMID与操作系统的进程ID(PID)是一致的,使用UNIX的ps命令也可以查到虚拟机的LVMID,但如果同时启动了多个虚拟机进程,无法根据进程名称定位时,那就只能依赖jps命令显示主类的功能来区分了。
```jps [options] [hostid]```
选项 | 作用 |
---|---|
-q | 只输出LVMID,省略主类的名称 |
-m | 输出虚拟机进程启动时传递给主类main()函数的参数 |
-l | 输出主类的全名,如果进程执行的是Jar包,输出jar的路径 |
-v | 输出虚拟机进程启动时的JVM参数 |
例子:
[root@VM_0_13_centos data]# jps -q
32534
26489
[root@VM_0_13_centos data]# jps -m
26565 Jps -m
32534 jar --spring.profiles.active=prod
[root@VM_0_13_centos data]# jps -l
26641 sun.tools.jps.Jps
32534 eladmin-system-2.1.jar
[root@VM_0_13_centos data]# jps -v
26707 Jps -Denv.class.path=.:/usr/local/java/jdk1.8.0_201/lib/dt.jar:/usr/local/java/jdk1.8.0_201/lib/tools.jar -Dapplication.home=/usr/local/java/jdk1.8.0_201 -Xms8m
32534 jar
jstat 是用于监视虚拟机各种运行状态信息的命令行工具,它可以显示本地或者远程虚拟机进程的类装载、内存、垃圾收集、JIT编译等运行时数据,在没有图形界面,只提供纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。
jstat [option vmid [interval[s|ms] [count]] ]
对于命令格式中的VMID和LVMID需要特别说明一下,如果是本地虚拟机进程,VMID与LVMID是一致的,如果是远程虚拟机进程,那VMID的格式应该是:
[protocol:][//]lvmid[@hostname[:port]/servername]
参数interval 和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次,假设需要每1000毫秒查询一次进程32534垃圾收集状况,一共查询5次,那命令应当是:
jstat -gc 32534 1000 5
选项option 代表着用户希望查询的虚拟机信息,主要分三类:类装载、垃圾收集、运行期编译状况
选项 | 作用 |
---|---|
-class | 监视类装载、卸载数量、总空间以及类装载所耗费的时间 |
-gc | 监视Java堆状况,包括Eden区、两个survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息 |
-gccapacity | 与-gc基本相同,主要关注Java堆各个区域使用到的最大、最小空间 |
-gcutil | 与-gc基本相同,主要关注已使用空间占总空间的百分比 |
-gccause | 与-gc基本相同,但是会额外输出导致上一次GC产生的原因 |
-gcnew | 监视新生代GC状况 |
-gcnewcapacity | 与-gcnew基本基本一致,主要关注使用到的最大、最小空间 |
-gcold | 监视老年代GC状况 |
-gcoldcapacity | 与-gcold基本基本一致,主要关注使用到的最大、最小空间 |
-gcpermcapacity | 永久代最大最小空间,1.8不支持 |
-compiler | 输出JIT编译器编译过的方法、耗时等信息 |
-printcompilation | 输出已经被被JIT编译的方法 |
例子:
[root@VM_0_13_centos data]# jstat -class 32534 500 3
Loaded Bytes Unloaded Bytes Time
16207 15759.6 11 7.3 20.00
16207 15759.6 11 7.3 20.00
16207 15759.6 11 7.3 20.00
[root@VM_0_13_centos data]# jstat -gc 32534 500 3
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
2496.0 2496.0 0.0 68.1 20032.0 13360.0 50036.0 47532.1 55168.0 53247.6 0.0 0.0 2405 11.317 5 0.401 11.718
2496.0 2496.0 0.0 68.1 20032.0 13360.0 50036.0 47532.1 55168.0 53247.6 0.0 0.0 2405 11.317 5 0.401 11.718
2496.0 2496.0 0.0 68.1 20032.0 13360.0 50036.0 47532.1 55168.0 53247.6 0.0 0.0 2405 11.317 5 0.401 11.718
[root@VM_0_13_centos data]# jstat -gccapacity 32534 500 3
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
5440.0 87360.0 25024.0 2496.0 2496.0 20032.0 10944.0 174784.0 50036.0 50036.0 0.0 55600.0 55168.0 0.0 0.0 0.0 2405 5
5440.0 87360.0 25024.0 2496.0 2496.0 20032.0 10944.0 174784.0 50036.0 50036.0 0.0 55600.0 55168.0 0.0 0.0 0.0 2405 5
5440.0 87360.0 25024.0 2496.0 2496.0 20032.0 10944.0 174784.0 50036.0 50036.0 0.0 55600.0 55168.0 0.0 0.0 0.0 2405 5
[root@VM_0_13_centos data]# jstat -gcutil 32534 500 3
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 2.73 67.42 95.00 96.52 - 2405 11.317 5 0.401 11.718
0.00 2.73 67.42 95.00 96.52 - 2405 11.317 5 0.401 11.718
0.00 2.73 67.42 95.00 96.52 - 2405 11.317 5 0.401 11.718
[root@VM_0_13_centos data]# jstat -gccause 32534 500 3
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC
0.00 2.73 67.42 95.00 96.52 - 2405 11.317 5 0.401 11.718 Allocation Failure No GC
0.00 2.73 67.42 95.00 96.52 - 2405 11.317 5 0.401 11.718 Allocation Failure No GC
0.00 2.73 67.42 95.00 96.52 - 2405 11.317 5 0.401 11.718 Allocation Failure No GC
[root@VM_0_13_centos data]# jstat -gcnew 32534 500 3
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
2496.0 2496.0 0.0 68.1 15 15 1248.0 20032.0 13508.8 2405 11.317
2496.0 2496.0 0.0 68.1 15 15 1248.0 20032.0 13508.8 2405 11.317
2496.0 2496.0 0.0 68.1 15 15 1248.0 20032.0 13508.8 2405 11.317
[root@VM_0_13_centos data]# jstat -gcnewcapacity 32534 500 3
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
5440.0 87360.0 25024.0 8704.0 2496.0 8704.0 2496.0 69952.0 20032.0 2405 5
5440.0 87360.0 25024.0 8704.0 2496.0 8704.0 2496.0 69952.0 20032.0 2405 5
5440.0 87360.0 25024.0 8704.0 2496.0 8704.0 2496.0 69952.0 20032.0 2405 5
[root@VM_0_13_centos data]# jstat -gcold 32534 500 3
MC MU CCSC CCSU OC OU YGC FGC FGCT GCT
55168.0 53247.6 0.0 0.0 50036.0 47532.1 2405 5 0.401 11.718
55168.0 53247.6 0.0 0.0 50036.0 47532.1 2405 5 0.401 11.718
55168.0 53247.6 0.0 0.0 50036.0 47532.1 2405 5 0.401 11.718
[root@VM_0_13_centos data]# jstat -gcoldcapacity 32534 500 3
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
10944.0 174784.0 50036.0 50036.0 2405 5 0.401 11.718
10944.0 174784.0 50036.0 50036.0 2405 5 0.401 11.718
10944.0 174784.0 50036.0 50036.0 2405 5 0.401 11.718
jdk 1.8永久代已移出
[root@VM_0_13_centos data]# jstat -gcpermcapacity 32534 500 3
Unknown option: -gcpermcapacity
[root@VM_0_13_centos data]# jstat -compiler 32534 500 3
Compiled Failed Invalid Time FailedType FailedMethod
80817 0 0 44.38 0
80817 0 0 44.38 0
80817 0 0 44.38 0
[root@VM_0_13_centos data]# jstat -printcompilation 32534 500 3
Compiled Size Type Method
80817 566 1 ch/qos/logback/classic/joran/ReconfigureOnChangeTask run
80817 566 1 ch/qos/logback/classic/joran/ReconfigureOnChangeTask run
80817 566 1 ch/qos/logback/classic/joran/ReconfigureOnChangeTask run
输出结果解析,以gcutil为例
[root@VM_0_13_centos data]# jstat -gcutil 32534 500 3
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 2.73 70.64 95.00 96.52 - 2405 11.317 5 0.401 11.718
新生代Eden区使用了70.64%的空间,Survivor0(S0,表示Survivor0)区里面是空的,Survivor1(S1,表示Survivor1)区已使用2.73%,老年代(O,表示Old)和元空间(Metaspace)分别使用了95.00% 和96.52的空间。程序自运行以来总共发生Minor GC(YGC,表示Young GC) 2405次,总耗时11.317(YGCT, T表示Time)秒,发生Full GC (FGC,表示Full GC)5次,Full GC(FGCT)总耗时为0.401,所有GC(GCT)总耗时为11.718秒。
由此可以发现,虽然一个服务单次Minor GC耗时虽然非常的短,可以忽略不计,但是当你的服务运行久了之后,随着GC次数的增加,导致的GC耗时也是不能忽视的开销,这也侧面说明了为什么之前面试互联网公司会被频繁问到的JVM已经JVM调优思路的由来。
关于以上输出简写的含义可以参加百度,或者查看下面的链接:
jstat 详解:https://www.cnblogs.com/yjd_hycf_space/p/7755633.html
jinfo的作用是实时查看和调整虚拟机各项参数,使用jps命令的-v参数可以查看虚拟机启动时显示指定的参数列表,但如果想知道未被显示指定的参数的系统默认值,除了去找资料外,就只能使用jinfo的-flag选项进行查询了(如果使用JDK1.6以上,使用java -XX:+PrintFlagsFinal查看参数默认值),jinfo 还可以使用-sysprps选项把虚拟机进程的System.getProperties()的内容打印出来。在JDK1.6之后,jfino 可以使用-flag [+/-]name 或者-flag name=vlaue修改一部分运行期可写的虚拟机参数值。
注:WINDOWS平台兼容性不是很好
jinfo 命令格式:
jinfo [option] pid
例子:
查询CMSInitiatingOccupancyFraction的值
[root@VM_0_13_centos data]# jinfo -flag CMSInitiatingOccupancyFraction 32534
-XX:CMSInitiatingOccupancyFraction=-1
[root@VM_0_13_centos data]# jinfo -sysprops 32534
Attaching to process ID 32534, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 25.201-b09
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.201-b09
sun.boot.library.path = /usr/local/java/jdk1.8.0_201/jre/lib/i386
java.protocol.handler.pkgs = org.springframework.boot.loader
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
省略。。。。。。。
今天先分享这么多,改天扶我起来,接着分享。
另外学习JVM,推荐周志明的《深入理解Java虚拟机》
这篇不出意外应该是2019年的最后一篇博客了,抖音、网易云、微博都出了年终总结,而我从学校出来都快两年了,摸起鱼来这日子过得还真是快,2020年立个flag,赶紧要找个对象成为顶级程序员,另外许愿20年年后能拿到阿里offer,
2019.12.30