深入理解java虚拟机——第四章笔记


虚拟机性能监控、故障处理工具

Java开发人员肯定都知道JDKbin目录中有javajavac这两个命令行工具,但并非所有程序 员都了解过JDKbin目录下其他各种小工具的作用。随着JDK版本的更迭,这些小工具的数量和功能 也在不知不觉地增加与增强。除了编译和运行Java程序外,打包、部署、签名、调试、监控、运维等 各种场景都可能会用到它们。

一. 基础故障处理工具

笔者这边使用的java版本为1.8.0_191,使用的是mac.

我们看一下$JAVA_HOME/bin下的文件:

[asdsw@izuf6ekene8xsqnzg2v3qcz bin]$ ll
总用量 896
-rwxr-xr-x 1 asdsw asdsw   8592 106 2018 appletviewer
lrwxrwxrwx 1 asdsw asdsw      8 112 2018 ControlPanel -> jcontrol
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 extcheck
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 idlj
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 jar
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 jarsigner
-rwxr-xr-x 1 asdsw asdsw   8464 106 2018 java
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 javac
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 javadoc
-rwxr-xr-x 1 asdsw asdsw   2293 912 2018 javafxpackager
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 javah
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 javap
-rwxr-xr-x 1 asdsw asdsw   2293 912 2018 javapackager
-rwxr-xr-x 1 asdsw asdsw   1809 106 2018 java-rmi.cgi
-rwxr-xr-x 1 asdsw asdsw 140248 106 2018 javaws
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 jcmd
-rwxr-xr-x 1 asdsw asdsw   8608 106 2018 jconsole
-rwxr-xr-x 1 asdsw asdsw   6264 106 2018 jcontrol
-rwxr-xr-x 1 asdsw asdsw   8600 106 2018 jdb
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 jdeps
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 jhat
-rwxr-xr-x 1 asdsw asdsw   8648 106 2018 jinfo
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 jjs
-rwxr-xr-x 1 asdsw asdsw   8648 106 2018 jmap
-rwxr-xr-x 1 asdsw asdsw  74675 128 2017 jmc
-rwxr-xr-x 1 asdsw asdsw    402 128 2017 jmc.ini
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 jps
-rwxr-xr-x 1 asdsw asdsw   8592 106 2018 jrunscript
-rwxr-xr-x 1 asdsw asdsw   8600 106 2018 jsadebugd
-rwxr-xr-x 1 asdsw asdsw   8648 106 2018 jstack
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 jstat
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 jstatd
-rwxr-xr-x 1 asdsw asdsw   5110 115 2017 jvisualvm
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 keytool
-rwxr-xr-x 1 asdsw asdsw   8592 106 2018 native2ascii
-rwxr-xr-x 1 asdsw asdsw   8656 106 2018 orbd
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 pack200
-rwxr-xr-x 1 asdsw asdsw   8592 106 2018 policytool
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 rmic
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 rmid
-rwxr-xr-x 1 asdsw asdsw   8592 106 2018 rmiregistry
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 schemagen
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 serialver
-rwxr-xr-x 1 asdsw asdsw   8592 106 2018 servertool
-rwxr-xr-x 1 asdsw asdsw   8656 106 2018 tnameserv
-rwxr-xr-x 1 asdsw asdsw 182536 106 2018 unpack200
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 wsgen
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 wsimport
-rwxr-xr-x 1 asdsw asdsw   8584 106 2018 xjc

1. jps

虚拟机进程状况工具

可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(main()函数所在的类)名称以及这些进程的本地虚拟机唯一 ID(LVMID,Local Virtual Machine Identifier)。对于本地虚拟机进程来说,LVMID与操作系统的进程ID(PID,Process Identifier)是一致的。

命令格式

jps [-q] [-mlvV] [<hostid>]

注:jps还可以通过RMI协议查询开启了RMI服务的远程虚拟机进程状态,参数hostidRMI注册表中 注册的主机名.

主要选项
选项 说明
-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>]]

注:对于命令格式中的VMIDLVMID需要特别说明一下:如果是本地虚拟机进程,VMIDLVMID 是一致的;如果是远程虚拟机进程,那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 输出已经被即时编译的方法
示例

参数intervalcount代表查询间隔和次数,如果省略这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

详细说明示例:

image-20210218165630660

3. jinfo

实时查看和调整虚拟机各项参数。

使用jps命令的-v参 数可以查看虚拟机启动时显式指定的参数列表,但如果想知道未被显式指定的参数的系统默认值,除了去找资料外,就只能使用jinfo-flag选项进行查询了(如果只限于JDK6或以上版本的话,使用javaXX:+PrintFlagsFinal查看参数默认值也是一个很好的选择)。jinfo还可以使用-sysprops选项把虚拟机进程的System.getProperties()的内容打印出来。这个命令在JDK5时期已经随着Linux版的JDK发布,当 时只提供了信息查询的功能,JDK 6之后,jinfoWindows和Linux平台都有提供,并且加入了在运行期 修改部分参数值的能力(可以使用-flag[+|-]name或者-flag name=value在运行期修改一部分运行期可写的虚拟机参数值)。在JDK6中,jinfo对于Windows平台功能仍然有较大限制,只提供了最基本的-flag选项。

命令格式

jinfo [option] <pid>

示例

查看最大堆内存:

[asdsw@izuf6ekene8xsqnzg2v3qcz ~]$ jinfo -flag MaxHeapSize 7363
-XX:MaxHeapSize=482344960

4. jmap

生成堆转储快照(一般称为heapdumpdump文件)。

如果不使用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 218 17:25 abc

5. jhat

JDK提供jhat(JVM Heap Analysis Tool)命令与jmap搭配使用,来分析jmap生成的堆转储快照。 jhat内置了一个微型的HTTP/Web服务器,生成堆转储快照的分析结果后,可以在浏览器中查看。不过 实事求是地说,在实际工作中,除非手上真的没有别的工具可用,否则多数人是不会直接使用jhat命令 来分析堆转储快照文件的,主要原因有两个方面。一是一般不会在部署应用程序的服务器上直接分析堆转储快照,即使可以这样做,也会尽量将堆转储快照文件复制到其他机器上进行分析,因为分析 工作是一个耗时而且极为耗费硬件资源的过程,既然都要在其他机器上进行,就没有必要再受命令行工具的限制了。另外一个原因是jhat的分析功能相对来说比较简陋,后文将会介绍到的VisualVM,以及专业用于分析堆转储快照文件的Eclipse Memory AnalyzerIBM 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可以看到分析结 果,如图所示。

image-20210218173925219

6. jstack

jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者 javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。线程出现停顿时通过jstack来查看各个线程的调用堆栈, 就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源。

命令格式

jstack [option] vmid

主要选项
选项 说明
-F 当正常输出的请求不被响应时,强制输出线程堆栈
-l 除堆栈外,显示关于锁的附加信息
-m 如果调用到本地方法的话,可以显示C/C++的堆栈

二. 可视化故障处理工具

1. jhsdb

JDK中提供了jcmdjhsdb两个集成式的多功能工具箱,它们不仅整合了上一节介绍到的所有 基础工具所能提供的专项功能,而且由于有着“后发优势”,能够做得往往比之前的老工具们更好、更强大,表是jcmdjhsdb与原基础工具实现相同功能的简要对比:

image-20210218183314695

jhsdb是一款基于服务性代理(Serviceability AgentSA)实现的进程外调试工具。服务性代理是HotSpot虚拟机中一组用于映射Java虚拟机运行信息的、主要基于Java语言(含少量JNI代码)实现的 API集合。服务性代理以HotSpot内部的数据结构为参照物进行设计,把这些C++的数据抽象出Java模 型对象,相当于HotSpotC++代码的一个镜像。通过服务性代理的API,可以在一个独立的Java虚拟机的进程里分析其他HotSpot虚拟机的内部数据,或者从HotSpot虚拟机进程内存中dump出来的转储快照里还原出它的运行状态细节。服务性代理的工作原理跟Linux上的GDB或者Windows上的Windbg是相似的。

2. jconsole

jconsole(Java Monitoring and Management Console)是一款基于JMX(Java Manage-ment Extensions)的可视化监视、管理工具。它的主要功能是通过JMXMBean(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的性能分析功能比起JProfilerYourKit等专业且收费的Profiling工具都不遑多让。而且相比这些第三方工具,VisualVM还有一个很大的优点:不需要被监视的 程序基于特殊Agent去运行,因此它的通用性很强,对应用程序实际性能的影响也较小,使得它可以直接应用在生产环境中。这个优点是JProfilerYourKit等工具无法与之媲美的。

4. java mission control

可持续在线的监控工具


文章作者: shiv
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 shiv !
评论
  目录