Java 虚拟机系列(四)性能监控、故障处理工具总结
Monitoring Tools and Commands
https://www.saashub.com/compare-visualvm-vs-jconsole
命令/工具 | 全称 | 作用 |
---|---|---|
jps |
JVM Process Status Tool | You use the jps command to list the instrumented JVMs on the target system.显示正在运行的所有 HotSpot VM 进程。 |
jstat |
JVM Statistics Monitoring Tool | You use the jstat command to monitor JVM statistics.用于监视本地或远程 HotSpot VM 各方面的运行数据,例如类加载/卸载、运行时数据区、GC、JIT。 |
jconsole |
You use the jconsole command to start a graphical console to monitor and manage Java applications.JDK 5 起免费提供。一款基于 JMX (Java Management Extensions) 的可视化监视、管理工具。它的主要功能是通过 JMX 的 MBean (Managed Bean) 对系统进行信息收集和参数动态调整。 |
|
VisualVM | VisualVM is a visual tool integrating commandline JDK tools and lightweight profiling capabilities. |
jps
jps
命令的功能与 ps
类似,用于列出正在运行的 JVM 进程状态。
常用参数:
-q
只输出 LVMID,省略主类的名称。-l
输出主类的全名,如果进程执行的是 JAR 包,则输出 JAR 路径。-m
输出虚拟机进程启动时传递给主类main()
函数的参数。-v
输出虚拟机进程启动时的 JVM 参数。
jstat
jstat
命令用于监视当前 JVM 的各种运行状态信息。在用户体验上也许不如 JMC、VisualVM 等可视化监控工具以图表形式展示那样直观,但在实际生产环境中不一定可以使用 GUI 图形界面,因此在没有 GUI、只提供命令行界面的服务器上,仍是运行期定位虚拟机性能问题的常用工具。
命令格式:
1 | $ jstat options vmid [interval[s|ms] [count]] |
常用参数:
- options,要查询的虚拟机信息,主要分为三类:
- 类加载
-class
监视类加载、卸载数量、总空间以及类加载所耗费的时间
- 运行时数据区、GC
-gccapacity
查看 GC 情况和 JVM 各区的容量(字节)-gc
查看 GC 情况和 JVM 各区的容量和使用量(字节)-gcutil
查看 GC 情况和 JVM 各区的使用率(%)- …
- JIT
-compiler
输出即时编译器编译过的方法、耗时等信息-printcompilation
输出已经被即时编译的方法
- 类加载
- vmid,如果是本地虚拟机进程,VMID 与 LVMID 一致;如果是远程虚拟机进程,则 VMID 的格式为:
[protocol:][//]lvmid[@hostname[:port]/servername]
- interval,间隔时间,单位为秒或者毫秒
- count,打印次数,如果缺省则打印无数次
示例展示:
此示例连接到 lvmid 21891,并以 250 毫秒的间隔获取 7 个样本,每 6 行显示一次标题([-h<lines>]
),并显示由 -gcutil
选项指定的输出:
1 | $ jstat -gcutil -h6 21891 250 7 |
该示例结果显示,对象首先都在 Eden 区中创建,在第 3 和第 4 个样本之间由于 Eden 区装满,发生了 Young GC, gc 耗时 0.001 秒,并将对象从 Eden 区(E)提升到 Old 区(O),导致 Old 区的使用率从 9.49% 增加到 9.51%。
-gcutil
选项每列说明:
列名 | 描述 |
---|---|
S0 | Survivor space 0 区占用率 |
S1 | Survivor space 1 区占用率 |
E | Eden space 区占用率 |
O | Old space 区占用率 |
P | Perm space 区占用率 |
列名 | 描述 |
---|---|
YGC | 从应用程序启动到采样时发生 Young GC 的次数,E 区满后触发 |
YGCT | 从应用程序启动到采样时 Young GC 所用的时间(单位秒) |
FGC | 从应用程序启动到采样时发生 Full GC 的次数, O 区满后触发 |
FGCT | 从应用程序启动到采样时 Full GC 所用的时间(单位秒) |
GCT | 从应用程序启动到采样时用于垃圾回收的总时间(单位秒) |
VisualVM
VisualVM 脱胎于自 JDK 6 起免费提供的 jvisualvm
,目前已经从 Oracle JDK 中分离出来,成为一个独立发展的开源项目:https://visualvm.github.io/
功能:
监控进程的 CPU 使用率、内存(运行时数据区)、类加载、线程等统计;
监控线程状态。如下图:
VisualVM 拥有丰富的插件扩展。例如:
Visual GC
Integration of the Visual GC tool into VisualVM. Visual GC user interface is displayed for each local or remote application with performance counters available via jvmstat API.
The Visual GC tool attaches to an instrumented HotSpot JVM and collects and graphically displays garbage collection, class loader, and HotSpot compiler performance data.
Threads Inspector
Threads Inspector adds a new section to the Threads tab showing stack traces for the selected live threads.
TDA Plugin
Thread Dump Analyzer is a GUI for analyzing thread dumps generated by the Java VM.
Troubleshooting Tools and Commands
Troubleshooting Tools and Commands
命令 | 全称 | 作用 | 备注 |
---|---|---|---|
jinfo |
Configuration Info for Java | You use the jinfo command to generate Java configuration information for a specified Java process.实时显示或修改虚拟机配置信息。 |
在 JDK 9 中已集成到 jhsdb |
jstack |
Stack Trace for Java | You use the jstack command to print Java stack traces of Java threads for a specified Java process.显示虚拟机当前时刻的线程快照(thread dump/javacore 文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成堆栈快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。 |
在 JDK 9 中已集成到 jhsdb |
jmap |
Memory Map for Java | You use the jmap command to print details of a specified process.用于实时生成 JVM 堆内存转储快照(heap dump/hprof 文件),或查看堆内存信息。其它转储方法: -XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpOnCtrlBreak |
在 JDK 9 中已集成到 jhsdb |
jhat |
JVM Heap Dump Browser | 用于分析 heap dump 文件,它会建立一个 HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果。分析结果默认以包为单位进行分组显示,分析内存泄漏问题主要会使用到其中的 Heap Histogram(与 jmap -histo 功能一样)与 OQL 页签功能,前者可以找到内存中总容量最大的对象,后者是标准的对象查询语言,使用类似 SQL 的语法堆内存中的对象进行查询统计。 |
在 JDK 9 中已被 jhsdb 替代 |
jhsdb |
Java HotSpot Debugger | 一个基于 Serviceability Agent 的 HotSpot 进程调试器。 | 自 JDK 9 起免费提供 |
jstack
jstack
命令用于 thread dump(生成虚拟机的线程堆栈快照),根据堆栈信息我们可以定位到具体代码,所以它在 JVM 性能调优中使用得非常多。
1 | $ jstack 21090 > /tmp/threaddump |
由于导出的 threaddump
文件非常大,可以先统计下所有线程、或关注的线程分别处于什么状态:
1 | $ grep /tmp/threaddump | awk '{print $2$3$4$5}' | sort | uniq -c | sort |
发现有大量 WAITING (parking)
状态的线程。重新打开 threaddump
文件排查,根据堆栈可以定位到具体的问题代码,可以初步判断是 HTTP 连接耗尽资源导致的问题。
jmap
常用参数:
-dump
实时生成 JVM 堆内存转储快照(heap dump/hprof 文件)。格式为-dump:[live,] format=b, file=<filename>
,其中live
子参数表示是否只 dump 出存活的对象。-histo[:live]
显示堆中对象统计信息,包括类、实例数量、合计容量。-heap
查看当前堆内存的详细信息,如Heap Configuration
、Heap Usage
。
1 | $ jmap -heap 7059 |
注意:
Heap Configuration | Heap Usage | |
---|---|---|
JDK 7 及以下版本 | PermSize 、MaxPermSize |
Heap 中包含 Perm Generation |
JDK 8 及以上版本 | MetaspaceSize 、MaxMetaspaceSize |
Heap 不再包含 Perm Generation,取而代之的是在 Heap 之外有一块 Metaspace |
可以进一步分析对象分布。
反汇编工具
大多数情况下,通过诸如javap等反编译工具来查看源码的字节码已经能够满足我们的日常需求,但是不排除在有些特定场景下,我们需要通过反汇编来查看相应的汇编指令。两个很好用的工具——HSDIS、JITWatch
工具 | 描述 |
---|---|
HSDIS (HotSpot disassembler) | 一款 HotSpot 虚拟机 JIT 编译代码的反汇编插件。 |
JITWatch | 用于可视化分析。 |
https://zhuanlan.zhihu.com/p/158168592?from_voters_page=true
参考
《深入理解 Java 虚拟机》
https://docs.oracle.com/en/java/javase/11/tools/index.html