1. jps
jps
(JVM Process Status Tool)可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()
方法所在的类)名称以及这些进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVMID)。虽然功能比较单一,但它是使用频率最高的JDK命令行工具,因为其他的JDK工具大多需要输入它查询到的LVMID来确定要监控的是哪一个虚拟机进程。对于本地虚拟机进程来说,LVMID与操作系统的进程ID(Process Identifier,PID)是一致的,使用Windows的任务管理器或者UNIX的ps命令也可以查询到虚拟机进程的LVMID,但如果同时启动了多个虚拟机进程,无法根据进程名称定位时,那就只能依赖jps命令显示主类的功能才能区分了。
注:Oracle官方提供的
jps
命令的参考文档地址为https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
1.1. jps命令格式
jps
命令格式为如下:
- ubuntu@s100:~$ jps -help
- usage: jps [-help]
- jps [-q] [-mlvV] [<hostid>]
各类参数的意义如下:
选项 | 作用 |
---|---|
-q |
只输出LVMID,省略主类的名称 |
-m |
输出虚拟机进程启动时传递给主类main() 方法的参数 |
-l |
输出主类的全名,如果进程执行的是Jar包,输出Jar包路径 |
-v |
输出虚拟机进程启动时的JVM参数 |
1.2. jps使用演示
下面展示了jps
各类参数的不同输出:
- ubuntu@s100:~$ jps -q
- 8037
- 2281
- ubuntu@s100:~$ jps -m
- 2281 Bootstrap start
- 8047 Jps -m
- ubuntu@s100:~$ jps -l
- 8057 sun.tools.jps.Jps
- 2281 org.apache.catalina.startup.Bootstrap
- ubuntu@s100:~$ jps -v
- 8067 Jps -Dapplication.home=/soft/jdk1.8.0_65 -Xms8m
- 2281 Bootstrap -Djava.util.logging.config.file=/soft/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Dignore.endorsed.dirs= -Dcatalina.base=/soft/tomcat -Dcatalina.home=/soft/tomcat -Djava.io.tmpdir=/soft/tomcat/temp
2. jinfo
jinfo
(Configuration Info for Java)的作用是实时地查看和调整虚拟机各项参数。使用jps命令的-v
参数可以查看虚拟机启动时显式指定的参数列表,但如果想知道未被显式指定的参数的系统默认值,除了去找资料外,就只能使用jinfo
的-flag
选项进行查询了(如果只限于JDK 1.6或以上版本的话,使用java -XX:+PrintFlagsFinal
查看参数默认值也是一个很好的选择),jinfo
还可以使用-sysprops
选项把虚拟机进程的System.getProperties()
的内容打印出来。这个命令在JDK 1.5时期已经随着Linux版的JDK发布,当时只提供了信息查询的功能,JDK 1.6之后,jinfo
在Windows和Linux平台都有提供,并且加入了运行期修改参数的能力,可以使用-flag[+|-]name
或者-flag name=value
修改一部分运行期可写的虚拟机参数值。JDK 1.6中,jinfo
对于Windows平台功能仍然有较大限制,只提供了最基本的-flag选项。
注:Oracle官方提供的
jinfo
命令的参考文档地址为https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
2.1. jinfo命令格式
jinfo
命令格式为如下:
- ubuntu@s100:~$ 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
各类参数的意义如下:
选项 | 作用 |
---|---|
-flag |
后跟参数名,用于打印参数值,或者设置某个参数值 |
-sysprops |
打印System.getProperties() 的内容 |
2.2. jinfo使用演示
- $ > jinfo -flags 2168
- Attaching to process ID 2168, please wait...
- Debugger attached successfully.
- Server compiler detected.
- JVM version is 25.144-b01
- Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4284481536 -XX:MaxNewSize=1428160512 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
- Command line: -Djava.util.logging.config.file=C:\Java\apache-tomcat-7.0.52\conf\logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=C:\Java\apache-tomcat-7.0.52\endorsed -Dcatalina.base=C:\Java\apache-tomcat-7.0.52 -Dcatalina.home=C:\Java\apache-tomcat-7.0.52 -Djava.io.tmpdir=C:\Java\apache-tomcat-7.0.52\temp
3. jstat
jstat
(JVM Statistics Monitoring Tool)是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程[1]虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。
注:Oracle官方提供的
jstat
命令的参考文档地址为https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
3.1. jstat命令格式
jstat
命令格式为如下:
- ubuntu@s100:~$ jstat
- invalid argument count
- Usage: jstat -help|-options
- jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
其中-<option>
可以是以下选项:
选项 | 作用 |
---|---|
-class |
监视类装载、卸载数量、总空间以及类装载所耗费的时间 |
-gc |
监视Java堆状况,包括Eden区、两个survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息 |
-gccapaclty |
监视内容与-gc 基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间 |
-gcutil |
监视内容与-gc 基本相同,但输出主要关注已使用空间占总空间的百分比 |
-gccause |
与-gcutil 功能一样,但是会额外输出导致上一次GC产生的原因 |
-gcnew |
监视新生代GC状况 |
-genewcapaclty |
监视内容与-gcnew 基本相同,输出主要关注使用到的最大、最小空间 |
-gcold |
监视老年代GC状况 |
-geoldcapacity |
监视内容与-gcold 基本相同,输出主要关注使用到的最大、最小空间 |
-gepermcapaclty |
输出永久代使用到的最大、最小空司 |
-compiler |
输出JIT编译器编译过的方法、耗时等信息 |
-printcompilation |
输出已经被JIT编译的方法 |
对于命令格式中的VMID与LVMID需要特别说明一下:如果是本地虚拟机进程,VMID与LVMID是一致的,如果是远程虚拟机进程,那VMID的格式应当是:
- [protocol:][//]lvmid[@hostname[:port]/servername]
注:当使用
jstat
来监视远程虚拟机进程时,需要远程主机提供RMI支持,Sun提供的jstatd
工具可以很方便地建立远程RMI服务器。
3.2. jstat使用演示
以JDK 1.8环境为例,这里介绍几个常用的参数。
使用-gc
参数来查看Java堆各个区域的垃圾回收状况,例如查看Tomcat的Java堆状况:
- ubuntu@s100:~$ jps
- 3300 Jps
- 2281 Bootstrap
- ubuntu@s100:~$ jstat -gc 2281
- S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
- 2112.0 2112.0 698.7 0.0 16896.0 5404.1 42368.0 17341.5 16768.0 16113.4 1920.0 1762.4 6 0.132 0 0.000 0.132
打印内容会反馈给我们列信息,这些列的含义如下:
- S0C、S1C、S0U、S1U:Survivor0和Survivor1区的总量和使用量。
- EC、EU:Eden区的总量和使用量。
- OC、OU:Old区的总量和使用量。
- MC、MU:Metaspace区总量和使用量。
- CCSC、CCSU:压缩类空间总量和使用量。
- YGC、YGCT:Young GC的次数和时间。
- FGC、FGCT:Full GC的次数和时间。
- GCT:总的GC时间。
在命令格式中,参数interval
和count
代表查询间隔和次数,如果省略这两个参数,说明只查询一次。假设需要每250毫秒查询一次进程2281垃圾收集状况,一共查询20次,那命令应当是:
- ubuntu@s100:~$ jstat -gc 2281 250 20
- S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
- 2112.0 2112.0 698.7 0.0 16896.0 10058.8 42368.0 17341.5 16768.0 16113.4 1920.0 1762.4 6 0.132 0 0.000 0.132
- 2112.0 2112.0 698.7 0.0 16896.0 10058.8 42368.0 17341.5 16768.0 16113.4 1920.0 1762.4 6 0.132 0 0.000 0.132
- 2112.0 2112.0 698.7 0.0 16896.0 10058.8 42368.0 17341.5 16768.0 16113.4 1920.0 1762.4 6 0.132 0 0.000 0.132
- 2112.0 2112.0 698.7 0.0 16896.0 10058.8 42368.0 17341.5 16768.0 16113.4 1920.0 1762.4 6 0.132 0 0.000 0.132
- 2112.0 2112.0 698.7 0.0 16896.0 10058.8 42368.0 17341.5 16768.0 16113.4 1920.0 1762.4 6 0.132 0 0.000 0.132
- ...
-gccapacity
参数可以看查看Java堆各个区域的内存状况:
- ubuntu@s100:~$ jstat -gccapacity 2281
- NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
- 21120.0 336512.0 21120.0 2112.0 2112.0 16896.0 42368.0 673152.0 42368.0 42368.0 0.0 1064960.0 16768.0 0.0 1048576.0 1920.0 6 0
列的含义如下:
NGCMN
:新生代使用到的最小内存大小(kB)。NGCMX
:新生代使用到的最大内存大小(kB)。NGC
:当前新生代使用到的内存大小(kB)。S0C
:当前Survivor0区使用到的内存大小(kB)。S1C
:当前Survivor1区使用到的内存大小(kB)。EC
:当前Eden区使用到的内存大小(kB)。OGCMN
:老年代使用到的最小内存大小(kB)。OGCMX
:老年代使用到的最小内存大小(kB)。OGC
:当前老年代使用到的内存大小(kB)。OC
:当前Old区使用到的内存大小(kB)。MCMN
:Metaspace区使用到的最小内存大小(kB)。MCMX
:Metaspace区使用到的最大内存大小(kB)。MC
:当前Metaspace区使用到的内存大小(kB)。CCSMN
:压缩类空间使用到的最小内存大小(kB)。CCSMX
:压缩类空间使用到的最大内存大小(kB)。CCSC
:当前压缩类空间使用到的内存大小(kB)。YGC
:Young GC发生的次数。FGC
:Full GC发生的次数。
-compiler
参数可以输出输出JIT编译器编译过的方法、耗时等信息:
- ubuntu@s100:~$ jstat -compiler 2281
- Compiled Failed Invalid Time FailedType FailedMethod
- 1858 0 0 5.00 0
列的含义如下:
Compiled
:JIT编译成功的方法数量。Failed
:JIT编译失败的方法数量。Invalid
:无效的编译任务数量。Time
:编译总耗时。FailedType
:最后一次失败编译的类型。FailedMethod
:最后一次失败编译的类名和方法名。
4. jmap
jmap
(Memory Map for Java)命令用于生成堆转储快照(一般称为heapdump或dump文件),还可以查询finalize执行队列、Java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。
如果不使用jmap
命令,要想获取Java堆转储快照,还有一些其他的方法:
- 使用
-XX:+HeapDumpOnOutOfMemoryError
参数,可以让虚拟机在OOM异常出现之后自动生成dump文件。 - 通过
-XX:+HeapDumpOnCtrlBreak
参数则可以使用+Ctrl++Break+键让虚拟机生成dump文件 - 或者在Linux系统下通过
Kill -3
命令发送进程退出信号,也能拿到dump文件。
jmap
有不少功能在Windows平台下都是受限的,除了生成dump文件的-dump
选项和用于查看每个类的实例、空间占用统计的-histo
选项在所有操作系统都提供之外,其余选项都只能在Linux/Solaris下使用。
注:Oracle官方提供的
jmap
命令的参考文档地址为https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jmap.html
4.1. jmap命令格式
jmap
命令有以下的格式:
- ubuntu@s100:~$ 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)
[option]
参数有以下的几类取值:
选项 | 作用 |
---|---|
-dump |
生成Java堆转储快照。格式为-dump:[live,]format=b,file=<filename ,其中live 子参数说明是否只dump出存活的对象 |
-finalizerinfo |
显示在F-Queue中等i寺Finalizer线程执行finalize方法的对象。只在Linux/Solaris平台下有效 |
-heap |
显示Java堆详细信息,如使用哪种回收器、参数配置、分代状况等。只在Linux/Solaris平台下有效 |
-histo |
显示堆中对象统计信息,包括类、实例数量、合计容量 |
-permstat |
以ClassLoader为统计口径显示永久代内存状态。只在Linux/Solaris平台下有效 |
-F |
当虚拟机进程对-dump 选项没有响应时,可使用这个选项强制生成dump快照。只在Linux/Solaris平台下有效 |
4.2. jmap使用演示
如使用jmap命令导出某个JVM进程的堆转储文件:
- ubuntu@s100:~$ jmap -dump:format=b,file=heap.hprof 2281
- Dumping heap to /home/ubuntu/heap.hprof ...
- Heap dump file created
- ubuntu@s100:~$ ls -lh heap.hprof
- -rw------- 1 ubuntu ubuntu 35M Oct 14 16:47 heap.hprof
查看某个进程堆中的对象统计信息:
- ubuntu@s100:~$ jmap -histo 2281
- num #instances #bytes class name
- ----------------------------------------------
- 1: 40653 9726648 [B
- 2: 49649 8085016 [C
- 3: 12086 1349168 [I
- 4: 46202 1108848 java.lang.String
- 5: 19071 610272 java.util.HashMap$Node
- 6: 11520 460800 java.util.HashMap$ValueIterator
- 7: 4981 438328 java.lang.reflect.Method
- 8: 11271 360672 java.io.File
- ...
1. jhat
Sun JDK提供jhat
(JVM Heap Analysis Tool)命令与jmap
搭配使用,来分析jmap生成的堆转储快照。jhat
内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看。不过实事求是地说,在实际工作中,除非笔者手上真的没有别的工具可用,否则一般都不会去直接使用jhat命令来分析dump文件,主要原因有二:一是一般不会在部署应用程序的服务器上直接分析dump文件,即使可以这样做,也会尽量将dump文件复制到其他机器上进行分析,因为分析工作是一个耗时而且消耗硬件资源的过程,既然都要在其他机器进行,就没有必要受到命令行工具的限制了;另一个原因是jhat
的分析功能相对来说比较简陋,后文将会介绍到的VisualVM,以及专业用于分析dump文件的Eclipse Memory Analyzer、IBM HeapAnalyzer等工具,都能实现比jhat
更强大更专业的分析功能。
注:Oracle官方提供的
jmap
命令的参考文档地址为https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jmap.html
2. jhat使用演示
在前面我们使用jmap
生成了一个heap.hprof的堆内存转储文件,我们可以使用jhat
分析该文件:
- ubuntu@s100:~$ jhat heap.hprof
- Reading from heap.hprof...
- Dump file created Sun Oct 14 01:47:30 PDT 2018
- Snapshot read, resolving...
- Resolving 322995 objects...
- Chasing references, expect 64 dots................................................................
- Eliminating duplicate references................................................................
- Snapshot resolved.
- Started HTTP server on port 7000
- Server is ready.
从打印信息Started HTTP server on port 7000
可知jhat
命令启动了一个服务器监听在7000端口,可以通过浏览器访问该地址,可以得到一个页面: