12-虚拟机性能监控、故障处理工具
从实践的角度去认识虚拟机内存管理的世界,给一个系统定位问题的时候,知识、经验是关键基础,数据是依据,工具是运用知识处理数据(数据包括但不限于异常堆栈、虚拟机运行日志、垃圾收集器日志、线程快照(threaddump./javacore文件)、堆转储快照(heapdump/hprof文件))的手段。恰当使用虚拟机故障处理分析的工具可以提升我们分析数据、定位并解决问题的效率,但应当意识到工具永远都是知识技能的一层包装,没有什么工具是“秘密武器”,拥有了就能“包治百病”。
一、基础故障处理工具
JDK中bin目录下工具
-
bin目录中除了编译和运行Java程序外,打包、部署、签名、调试、监控、运维等各种场景都可能会用到这些命令
JDK中bin目录.png
jps : 虚拟机进程状况工具
- 可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(LVMID,Local Virtual Machine Identifier)
jps 或 jps -l
jps工具主要选项.png
jstat : 虚拟机统计信息监视工具
- jstat(JVM Statistics Monitoring Tool) 是用于监视虚拟机各个运行状态信息的命令行工具。
- 可以显示本地或者远程虚拟机进程中的类加载、内存、垃圾收集、即时编译等运行时数据,在没有GUI图形界面、只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的常用工具。
jstat [ option vmid [interval[s|ms] [count]] ]
- 如果是本地虚拟机进程,VMID与LVMID是一致的;如果是远程虚拟机进程,那VMID的格式应当是
[protocol:][//]lvmid[@hostname[:port]/servername]
- 参数 interval 和 count 代表查询间隔和次数,如果省略这2个参数,说明只查询一次。例如:需要每250毫秒查询一次进程 2764 垃圾收集状况,一共查询 20 次,那命令应当是
jstat -gc 2764 250 20
- 选项 option 代表用户希望查询的虚拟机信息,主要分为三类:类加载、垃圾收集、运行期编译状况 jstat工具主要选项.png
-
jstat执行样例
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
1.78 0.00 53.99 70.64 95.96 93.66 52 1.772 4 1.185 2.956
- 参数说明
- S0、S1:表示Survivor0、Survivor1
- E:新生代Eden区,使用了53.99%的空间
- O:表示Old,使用了70.64%的空间
- M:元空间Metaspace,使用了95.96%
- CCS:压缩类空间利用率为93.66%
- YGC:表示Young GC/Minor GC,发生Minor GC 52次
- YGCT:YGC总耗时1.772秒
- FGC:表示Full GC,共发生4次
- FGCT:FGC总耗时1.185秒
- GCT:表示总GC Time,总耗时2.956秒
jinfo : Java配置信息工具
- jinfo(Configuration Info for Java)的作用是实时查看和调整虚拟机各项参数。使用jps命令的-v参数可以查看虚拟机启动时显示指定的参数列表,但如果想知道未被显示指定的参数的系统默认值,除了去找资料外,就只能使用jinfo的-flag选项进行查询了(使用java-XX: +PrintFlagsFinal查看参数默认值也是一个很好的选择)
- jinfo还可以使用-sysprops选项把虚拟机进程的System.getProperties()的内容打印出来
- jinfo 命令格式
jinfo [ option ] 16330
- 使用
jinfo -flag CMSInitiatingOccupancyFraction 16330
jmap : Java内存映像工具
-
jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为 heapdump 或 dump 文件)。
-
如果不使用 jmap 命令,要想获取 Java 堆转储快照也还有一些比较“暴力”的手段,如-XX:+HeapDumpOnOfMemoryError参数,可以让虚拟机在内存溢出异常出现之后自动生成堆转储快照文件
-
使用-XX:+HeapDumpOnCtrlBreak参数则可以使用Ctrl+Break键让虚拟机生成堆转储快照文件
-
jmap的作用并不仅仅是为了获取堆转储快照,它还可以查询finalize执行队列、Java堆和方法区的详细信息,如:空间使用率、当前使用的是哪种收集器
-
jmap命令格式
jmap [ option ] vmid
jmap -dump:format=b,file=raven.bin 16793
jmap工具主要选项.png
jhat : 虚拟机堆转储快照分析工具
-
JDK提供jhat(JVM Heap Analysis Tool)命令与jmap搭配使用,来分析jmap生成的堆转储快照。jhat内置了一个微型的HTTP/Web服务器,生成堆转储快照的分析结构后,可以在浏览器中查看。
-
分析使用jmap生成的dump文件
jhat raven.bin
Reading from raven.bin...
Dump file created Tue Jun 15 14:34:23 CST 2021
Snapshot read, resolving...
Resolving 6118027 objects...
Chasing references, expect 1223 dots.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Eliminating duplicate references.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
-
http://localhost:7000/ 查看分析结果
image.png
-
分析结构默认以包为单位进行分组显示,分析内存泄露问题主要使用到其中的“Heap Histogram”(与jmap-histo功能一样)与OQL页签的功能,前者可以找到内存中总容量最大的对象,后者是标准的对象查询语言,使用类似SQL的语法对内存中的对象进行查询统计。
jstack : Java堆栈跟踪工具
- jstack(Stack Trace for Java) 命令用于生产虚拟机当前时刻的线程快照(一般称为 threaddump或者Javacore文件)。
- 线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如:线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。
- 线程出现停顿时通过jstack来查看各个线程的调用堆栈,就可以获知没有响应的线程倒地在后台做写什么事情,或者等待着什么资源。
- jstack命令格式
jstack [ option ] vmid
-
jstack 工具主要选项
jstack 工具主要选项.png
基础工具总结
- 基础工具:用于支持基本的程序创建和运行 基础工具.png
- 安全:用于程序签名、设置安全测试等 安全.png
- 国际化:用于创建本地语言文件 国际化工具.png
- 远程方法调用:用于跨Web或网络的服务交互 远程方法调用工具.png
- Java IDL 与 RMI-IIOP:在JDK11中结束了十余年的CORBA支持,这些工具不再提供 image.png
- 部署工具:用于程序打包、发布和部署 部署工具.png
- Java Web Start Java Web Start.png
- 性能监控和故障处理:用于监控分析Java虚拟机运行信息 性能监控和故障处理.png
- WebService工具:与CORBA一起在JDK11中被移除 WebService工具.png
- REPL和脚本工具 REPL和脚本工具.png
二、可视化故障处理工具
JDK中除了附带大量的命令行工具外,还提供了几个功能集成度更高的可视化工具,用户可以使用这些可视化工具以更加便捷的方式进行进程故障诊断和调试工作。主要包括JConsole、JHSDB、VisualVM和JMC四个。
JHSDB:基于服务性代理的调试工具
- JDK中提供了JCMD和JHSDB两个集成式的多功能工具箱,它们不仅整合了上一节介绍到的所有基层工具所能提供的专项功能,而且由于有着“后发优势”,能够做得往往比之前的老工具们更好、更强大 JCMD、JHSDB和基础工具的对比.png
-
JHSDB是一款基于服务性代理(Serviceability Agent,SA)实现的进程外调试工具。服务性代理是HotSpot虚拟机中一组用于映射Java虚拟机运行信息的、主要基于Java语言(含少量JNI代码)实现的API集合。
-
服务性代理以HotSpot内部的数据结构为参照物进行设计,把这些C++的数据抽象出Java模型对象,相当于HotSpot的C++代码的一个镜像。
-
通过服务性代理的API,可以在一个独立的Java虚拟机的进程里分析其他HotSpot虚拟机的内部数据,或者从HotSpot虚拟机进程内存中dump出来的转储快照里还原出它的运行状态细节。
JHSDB实例测试
- 代码
package com.lkty.jhsdb;
/**
* JHSDB 测试代码
*
* staticObj、instanceObj、localObj 存放在哪里?
*/
public class JhsdbTest {
private static class ObjectHolder {}
static class Test {
static ObjectHolder staticObj = new ObjectHolder();
ObjectHolder instanceObj = new ObjectHolder();
void foo() {
ObjectHolder localObj = new ObjectHolder();
System.out.println(" done ");
}
}
public static void main(String[] args) {
Test test = new Test();
test.foo();
}
}
-
通过理论知识我们知道:
- staticObj随着Test的类型信息存放在方法区
- InstanceObj随着Test的对象实例方法到Java堆
- localObj则是存放在foo()方法栈帧的局部变量表中
-
使用JHSDB工具来验证上面理论是否正确
-
1、由于JHSDB本身对压缩指针的支持存在很多缺陷,建议在64位系统下禁用压缩指针。
-
2、为了后续操作是可以加快在内存中搜索对象的速度,建议限制一下Java堆的大小
-Xmx10m -XX:+UseSerialGC -XX:-UseCompressedOops