虚拟机性能监控、故障处理工具
Java开发人员肯定都知道
JDK
的bin
目录中有java
、javac
这两个命令行工具,但并非所有程序 员都了解过JDK
的bin
目录下其他各种小工具的作用。随着JDK
版本的更迭,这些小工具的数量和功能 也在不知不觉地增加与增强。除了编译和运行Java
程序外,打包、部署、签名、调试、监控、运维等 各种场景都可能会用到它们。
一. 基础故障处理工具
笔者这边使用的java版本为
1.8.0_191
,使用的是mac
.
我们看一下$JAVA_HOME/bin
下的文件:
[asdsw@izuf6ekene8xsqnzg2v3qcz bin]$ ll
总用量 896
-rwxr-xr-x 1 asdsw asdsw 8592 10月 6 2018 appletviewer
lrwxrwxrwx 1 asdsw asdsw 8 11月 2 2018 ControlPanel -> jcontrol
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 extcheck
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 idlj
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 jar
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 jarsigner
-rwxr-xr-x 1 asdsw asdsw 8464 10月 6 2018 java
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 javac
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 javadoc
-rwxr-xr-x 1 asdsw asdsw 2293 9月 12 2018 javafxpackager
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 javah
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 javap
-rwxr-xr-x 1 asdsw asdsw 2293 9月 12 2018 javapackager
-rwxr-xr-x 1 asdsw asdsw 1809 10月 6 2018 java-rmi.cgi
-rwxr-xr-x 1 asdsw asdsw 140248 10月 6 2018 javaws
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 jcmd
-rwxr-xr-x 1 asdsw asdsw 8608 10月 6 2018 jconsole
-rwxr-xr-x 1 asdsw asdsw 6264 10月 6 2018 jcontrol
-rwxr-xr-x 1 asdsw asdsw 8600 10月 6 2018 jdb
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 jdeps
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 jhat
-rwxr-xr-x 1 asdsw asdsw 8648 10月 6 2018 jinfo
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 jjs
-rwxr-xr-x 1 asdsw asdsw 8648 10月 6 2018 jmap
-rwxr-xr-x 1 asdsw asdsw 74675 12月 8 2017 jmc
-rwxr-xr-x 1 asdsw asdsw 402 12月 8 2017 jmc.ini
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 jps
-rwxr-xr-x 1 asdsw asdsw 8592 10月 6 2018 jrunscript
-rwxr-xr-x 1 asdsw asdsw 8600 10月 6 2018 jsadebugd
-rwxr-xr-x 1 asdsw asdsw 8648 10月 6 2018 jstack
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 jstat
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 jstatd
-rwxr-xr-x 1 asdsw asdsw 5110 1月 15 2017 jvisualvm
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 keytool
-rwxr-xr-x 1 asdsw asdsw 8592 10月 6 2018 native2ascii
-rwxr-xr-x 1 asdsw asdsw 8656 10月 6 2018 orbd
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 pack200
-rwxr-xr-x 1 asdsw asdsw 8592 10月 6 2018 policytool
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 rmic
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 rmid
-rwxr-xr-x 1 asdsw asdsw 8592 10月 6 2018 rmiregistry
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 schemagen
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 serialver
-rwxr-xr-x 1 asdsw asdsw 8592 10月 6 2018 servertool
-rwxr-xr-x 1 asdsw asdsw 8656 10月 6 2018 tnameserv
-rwxr-xr-x 1 asdsw asdsw 182536 10月 6 2018 unpack200
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 wsgen
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 wsimport
-rwxr-xr-x 1 asdsw asdsw 8584 10月 6 2018 xjc
1. jps
虚拟机进程状况工具
可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(main()函数所在的类)名称以及这些进程的本地虚拟机唯一 ID(LVMID,Local Virtual Machine Identifier)。对于本地虚拟机进程来说,LVMID与操作系统的进程ID(PID,Process Identifier)是一致的。
命令格式
jps [-q] [-mlvV] [<hostid>]
注:jps
还可以通过RMI
协议查询开启了RMI
服务的远程虚拟机进程状态,参数hostid
为RMI
注册表中 注册的主机名.
主要选项
选项 | 说明 |
---|---|
-q |
只输出LVMID ,省略主类的名称 |
-m |
输出虚拟机进程启动时传递给主类main() 函数的参数 |
-l |
输出主类的全名,如果进程执行的是jar 包,则输出jar 的路径 |
-v |
输出虚拟机进程启动时的jvm 参数 |
示例
[asdsw@izuf6ekene8xsqnzg2v3qcz ~]$ jps -l
7363 org.springframework.boot.loader.JarLauncher
8600 sun.tools.jps.Jps
[asdsw@izuf6ekene8xsqnzg2v3qcz ~]$ jps -v
7363 JarLauncher
8941 Jps -Dapplication.home=/home/asdsw/.sdkman/candidates/java/8.0.191-oracle -Xms8m
[asdsw@izuf6ekene8xsqnzg2v3qcz ~]$ jps -m
7363 JarLauncher run app.groovy -- --server.port=8765
8956 Jps -m
2. jstat
用于监控虚拟机各种运行状态信息的命令行工具,它可以显示本地或者远程虚拟机进程中的类加载、内存、垃圾收集、即时编译等运行时数据。
命令格式
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
注:对于命令格式中的VMID
与LVMID
需要特别说明一下:如果是本地虚拟机进程,VMID
与LVMID
是一致的;如果是远程虚拟机进程,那VMID
的格式应当是:[protocol:][//]lvmid[@hostname[:port]/servername]
主要选项
选项
option
代表用户希望查询的虚拟机信息,主要分为三类:类加载、垃圾收集、运行期编译状 况
选项 | 说明 |
---|---|
-class |
监视类加载、卸载数量、总空间以及类装载所耗费的时间 |
-gc |
监视java ·堆状况,包括eden 区、2个survivor 区、老年代、永久代等的容量,已用空间,垃圾收集时间合计等信息 |
-gccapacity |
监视内容与-gc 基本相同,但是输出主要关注java 堆各个区域使用到的最大最小空间 |
-gcutil |
监视内容与-gc 基本相同,但是输出主要关注已使用空间占总空间的百分比 |
-gccause |
与-gcutil 功能一样,但是会额外输出导致上一次垃圾收集产生的原因 |
-gcnew |
监视新生代垃圾收集状况 |
-gcnewcapacity |
监视内容与-gcnew 基本相同,但是输出主要关使用到的最大最小空间 |
-gcold |
监视老年代垃圾收集状况 |
-gcoldcapacity |
监视内容与-gcold 基本相同,但是输出主要关使用到的最大最小空间 |
-gcpermcapacity |
输出永久代使用到的最大最小空间 |
-compiler |
输出即时编译器编译过的方法、耗时等信息 |
-printcompilation |
输出已经被即时编译的方法 |
示例
参数interval
和count
代表查询间隔和次数,如果省略这2个参数,说明只查询一次。假设需要每250 毫秒查询一次进程7363
垃圾收集状况,一共查询20次,那命令应当是:
[asdsw@izuf6ekene8xsqnzg2v3qcz ~]$ jstat -gc 7363 200 2
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1152.0 1152.0 0.0 1135.9 9792.0 6900.3 24120.0 18487.6 43096.0 40991.5 5464.0 5026.0 93 0.342 2 0.139 0.480
1152.0 1152.0 0.0 1135.9 9792.0 6900.3 24120.0 18487.6 43096.0 40991.5 5464.0 5026.0 93 0.342 2 0.139 0.480
详细说明示例:
3. jinfo
实时查看和调整虚拟机各项参数。
使用jps
命令的-v
参 数可以查看虚拟机启动时显式指定的参数列表,但如果想知道未被显式指定的参数的系统默认值,除了去找资料外,就只能使用jinfo
的-flag
选项进行查询了(如果只限于JDK6
或以上版本的话,使用javaXX:+PrintFlagsFinal
查看参数默认值也是一个很好的选择)。jinfo
还可以使用-sysprops
选项把虚拟机进程的System.getProperties()
的内容打印出来。这个命令在JDK5
时期已经随着Linux
版的JDK
发布,当 时只提供了信息查询的功能,JDK 6
之后,jinfo
在Window
s和Linux
平台都有提供,并且加入了在运行期 修改部分参数值的能力(可以使用-flag[+|-]name
或者-flag name=value
在运行期修改一部分运行期可写的虚拟机参数值)。在JDK6
中,jinfo
对于Windows
平台功能仍然有较大限制,只提供了最基本的-flag
选项。
命令格式
jinfo [option] <pid>
示例
查看最大堆内存:
[asdsw@izuf6ekene8xsqnzg2v3qcz ~]$ jinfo -flag MaxHeapSize 7363
-XX:MaxHeapSize=482344960
4. jmap
生成堆转储快照(一般称为
heapdump
或dump
文件)。
如果不使用jmap
命令,要想获取Java堆转储快照也还有一些比较“暴力”的手段:譬如用-XX:+HeapDumpOnOutOfMemoryError
参数,可以让虚拟机在内存溢出异常出现之后自动生成堆转储快照文件,通过-XX:+HeapDumpOnCtrlBreak
参数则可以使用Ctrl + Break
键让虚拟机生成堆转储快 照文件,又或者在Linux
系统下通过Kill -3
命令发送进程退出信号“恐吓”一下虚拟机,也能顺利拿到堆转储快照。jmap
的作用不仅仅是为了获取堆转储快照,它还可以查询finalize
执行队列、Java
堆和方法区的详细信息,如空间使用率、当前用的是哪种收集器等。和jinfo
命令一样,jmap
有部分功能在Windows
平台下是受限的,除了生成堆转储快照的-dump
选项 和用于查看每个类的实例、空间占用统计的-histo
选项在所有操作系统中都可以使用之外,其余选项都只能在Linux/Solaris
中使用。
命令格式
jmap [option] <pid>
主要选项
选项 | 说明 |
---|---|
-dump |
生成java 堆转储快照。格式为-dump:[live,]format=b,file=<filename> ,其中live 子参数说明是否只dump 出存活的对象 |
-finalizerinfo |
显示在F-Queue 中等待Finalizer 线程执行finalize 方法的对象,只在Linux/Solaris 有效 |
-heap |
显示java 堆详细信息,如使用哪种回收器,参数配置、分代状况等,只在Linux/Solaris 有效 |
-histo |
显示堆中对象统计信息,包括类、实例数量、合计容量 |
-permstat |
以ClassLoader 为统计口径显示永久代内存状态,只在Linux/Solaris 有效 |
-F |
当虚拟机进程-dump 选项没有响应时,可使用这个选项强制生成dump 快照,只在Linux/Solaris 有效 |
示例
[asdsw@izuf6ekene8xsqnzg2v3qcz tmp]$ jmap -dump:format=b,file=abc 7363
Dumping heap to /tmp/abc ...
Heap dump file created
[asdsw@izuf6ekene8xsqnzg2v3qcz tmp]$ ll
总用量 68060
-rw------- 1 asdsw asdsw 45703038 2月 18 17:25 abc
5. jhat
JDK
提供jhat(JVM Heap Analysis Tool)
命令与jmap
搭配使用,来分析jmap
生成的堆转储快照。 jhat
内置了一个微型的HTTP/Web
服务器,生成堆转储快照的分析结果后,可以在浏览器中查看。不过 实事求是地说,在实际工作中,除非手上真的没有别的工具可用,否则多数人是不会直接使用jhat命令 来分析堆转储快照文件的,主要原因有两个方面。一是一般不会在部署应用程序的服务器上直接分析堆转储快照,即使可以这样做,也会尽量将堆转储快照文件复制到其他机器上进行分析,因为分析 工作是一个耗时而且极为耗费硬件资源的过程,既然都要在其他机器上进行,就没有必要再受命令行工具的限制了。另外一个原因是jhat
的分析功能相对来说比较简陋,后文将会介绍到的VisualVM
,以及专业用于分析堆转储快照文件的Eclipse Memory Analyzer
、IBM HeapAnalyzer
等工具,都能实现 比jhat
更强大专业的分析功能。
示例
[asdsw@izuf6ekene8xsqnzg2v3qcz tmp]$ jhat abc
Reading from abc...
Dump file created Thu Feb 18 17:25:00 CST 2021
Snapshot read, resolving...
Resolving 460091 objects...
Chasing references, expect 92 dots............................................................................................
Eliminating duplicate references............................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
用户在浏览器中输入http://localhost:7000可以看到分析结 果,如图所示。
6. jstack
jstack(Stack Trace for Java)
命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump
或者 javacore
文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。线程出现停顿时通过jstack来查看各个线程的调用堆栈, 就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源。
命令格式
jstack [option] vmid
主要选项
选项 | 说明 |
---|---|
-F |
当正常输出的请求不被响应时,强制输出线程堆栈 |
-l |
除堆栈外,显示关于锁的附加信息 |
-m |
如果调用到本地方法的话,可以显示C/C++ 的堆栈 |
二. 可视化故障处理工具
1. jhsdb
JDK
中提供了jcmd
和jhsdb
两个集成式的多功能工具箱,它们不仅整合了上一节介绍到的所有 基础工具所能提供的专项功能,而且由于有着“后发优势”,能够做得往往比之前的老工具们更好、更强大,表是jcmd
、jhsdb
与原基础工具实现相同功能的简要对比:
jhsdb
是一款基于服务性代理(Serviceability Agent
,SA
)实现的进程外调试工具。服务性代理是HotSpot
虚拟机中一组用于映射Java
虚拟机运行信息的、主要基于Java
语言(含少量JNI
代码)实现的 API
集合。服务性代理以HotSpot
内部的数据结构为参照物进行设计,把这些C++
的数据抽象出Java
模 型对象,相当于HotSpot
的C++
代码的一个镜像。通过服务性代理的API
,可以在一个独立的Java
虚拟机的进程里分析其他HotSpot
虚拟机的内部数据,或者从HotSpot
虚拟机进程内存中dump
出来的转储快照里还原出它的运行状态细节。服务性代理的工作原理跟Linux
上的GDB
或者Windows
上的Windbg
是相似的。
2. jconsole
jconsole(Java Monitoring and Management Console)
是一款基于JMX(Java Manage-ment Extensions)
的可视化监视、管理工具。它的主要功能是通过JMX
的MBean(Managed Bean)
对系统进行信息收集和参数动态调整。JMX
是一种开放性的技术,不仅可以用在虚拟机本身的管理上,还可以 运行于虚拟机之上的软件中,典型的如中间件大多也基于JMX
来实现管理与监控。虚拟机对JMX MBean
的访问也是完全开放的,可以使用代码调用API
、支持JMX
协议的管理控制台,或者其他符合 JMX
规范的软件进行访问。
3. jvisualvm
VisualVM(All-in-One Java Troubleshooting Tool)
是功能最强大的运行监视和故障处理程序之一, 曾经在很长一段时间内是Oracle
官方主力发展的虚拟机故障处理工具。Oracle
曾在VisualVM
的软件说明 中写上了“All-in-One”的字样,预示着它除了常规的运行监视、故障处理外,还将提供其他方面的能 力,譬如性能分析(Profiling)。VisualVM
的性能分析功能比起JProfiler
、YourKit
等专业且收费的Profiling
工具都不遑多让。而且相比这些第三方工具,VisualVM
还有一个很大的优点:不需要被监视的 程序基于特殊Agent
去运行,因此它的通用性很强,对应用程序实际性能的影响也较小,使得它可以直接应用在生产环境中。这个优点是JProfiler
、YourKit
等工具无法与之媲美的。
4. java mission control
可持续在线的监控工具