[6] 性能监控与故障处理工具
[6] 性能监控与故障处理工具

1. 基础工具

notion image

2. 命令行故障处理工具

2.1 jps(JVM 进程状况工具)

jps(JVM Process Status Tool)的功能也和 ps 命令类似:可以列出正在运行的 JVM 进程,并显示 JVM 执行主类(Main Class,main() 函数所在的类)名称以及这些进程的本地 JVM 唯一 ID(LVM ID,Local Virtual Machine Identifier)。
jps [ options ] [ hostid ]
jps -l
2388 D:\Develop\glassfish\bin\..\modules\admin-cli.jar
2764 com.sun.enterprise.glassfish.bootstrap.ASMain
3788 sun.tools.jps.Jps
jps 还可以通过 RMI 协议查询开启了 RMI 服务的远程 JVM 进程状态,参数 hostid 为 RMI 注册表中注册的主机名。
notion image

2.2 jstat(JVM 统计信息监视工具)

jstat(JVM Statistics M onitoring Tool)是用于监视 JVM 各种运行状态信息的命令行工具。它可以显示本地或者远程 JVM 进程中的类加载、内存、垃圾收集、即时编译等运行时数据,在没有 GUI 图形界面、只提供了纯文本控制台环境的服务器上,它将是运行期定位 JVM 性能问题的常用工 具。
jstat [ option vmid [interval[s|ms] [count]] ]
对于命令格式中的 VMID 与 LVMID 需要特别说明一下:如果是本地 JVM 进程,VMID 与 LVMID 是一致的;如果是远程 JVM 进程,那 VMID 的格式应当是:
[protocol:][//]lvmid[@hostname[:port]/servername]
参数 intervalcount 代表查询间隔和次数,如果省略这 2 个参数,说明只查询一次。假设需要每 250 毫秒查询一次进程 2764 垃圾收集状况,一共查询 20 次,那命令应当是:
jstat -gc 2764 250 20
选项 option 代表用户希望查询的 JVM 信息,主要分为三类:类加载、垃圾收集、运行期编译状况。
notion image
jstat -gcutil 2764
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 0.00 6.20 41.42 47.20 16 0.105 3 0.472 0.577
查询结果表明:这台服务器的新生代 Eden 区(E,表示 Eden)使用了 6.2 % 的空间,2 个 Survivor 区(S0、S1,表示 Survivor0、Survivor1)里面都是空的,老年代(O,表示 Old)和永久代(P,表示 Permanent)则分别使用了 41.42 % 和 47.20 % 的空间。程序运行以来共发生 Minor GC (YGC,表示 Young GC) 16 次,总耗时 0.105 秒;发生 Full GC(FGC,表示 Full GC )3 次,总耗时(FGCT,表示 Full GC Time)为 0.472 秒;所有 GC 总耗时(GCT,表示 GC Time)为 0.577 秒。

2.3 jinfo(Java 配置信息工具)

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

2.4 jmap(Java内存映像工具)

jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为 heapdump 或 dump 文件)。如果不使用 jmap 命令,要想获取 Java 堆转储快照也还有一些比较「暴力」的手段:譬如 - XX:+HeapDumpOnOutOfMemoryError 参数,可以让虚拟机在内存溢出异常出现之后自动生成堆转储快照文件,通过 -XX:+HeapDumpOnCtrlBreak 参数则可以使用 [Ctrl]+[Break] 键让虚拟机生成堆转储快照文件,又或者在 Linux 系统下通过 Kill -3 命令发送进程退出信号「恐吓」一下虚拟机,也能顺利拿到堆转储快照。
jmap [ option ] vmid
jmap 的作用并不仅仅是为了获取堆转储快照,它还可以查询 finalize 执行队列、Java 堆和方法区的详细信息,如空间使用率、当前用的是哪种收集器等。
和 jinfo 命令一样,jmap 有部分功能在 Windows 平台下是受限的,除了生成堆转储快照的 -dump 选项和用于查看每个类的实例、空间占用统计的 -histo 选项在所有操作系统中都可以使用之外,其余选项都只能在 Linux/Solaris 中使用。
jmap -dump:format=b,file=eclipse.bin 3500
Dumping heap to C:\Users\IcyFenix\eclipse.bin ...
Heap dump file created
使用 jmap 生成一个正在运行的 Eclipse 的堆转储快照文件,3500 是通过 jps 命令查询到的 LVMID。
notion image

2.5 jhat(JVM 堆转储快照分析工具)

JDK 提供 jhat(JVM Heap Analysis Tool)命令与 jmap 搭配使用,来分析 jmap 生成的堆转储快照。
jhat 内置了一个微型的 HTTP/Web 服务器,生成堆转储快照的分析结果后,可以在浏览器中查看。不过实事求是地说,在实际工作中,除非手上真的没有别的工具可用,否则多数人是不会直接使用 jhat 命令来分析堆转储快照文件的,主要原因有两个方面。一是一般不会在部署应用程序的服务器上直接分析堆转储快照,即使可以这样做,也会尽量将堆转储快照文件复制到其他机器上进行分析,因为分析工作是一个耗时而且极为耗费硬件资源的过程,既然都要在其他机器上进行,就没有必要再受命令行工具的限制了。另外一个原因是jhat的分析功能相对来说比较简陋,后文将会介绍到的 VisualVM ,以及专业用于分析堆转储快照文件的 Eclipse Memory Analyzer、IBM HeapAnalyzer 等工具,都能实现比 jhat 更强大专业的分析功能。
jhat eclipse.bin
Reading from eclipse.bin...
Dump file created Fri Nov 19 22:07:21 CST 2010
Snapshot read, resolving...
Resolving 1225951 objects...
Chasing references, expect 245 dots....
Eliminating duplicate references...
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
使用 jhat 分析上一节采用 jmap 生成的 Eclipse IDE 的内存快照文件。在浏览器中输入 http://localhost:7000/ 可以看到分析结果。

2.6 jstack(Java堆栈跟踪工具)

jstack(Stack Trace for Java)命令用于生成 JVM 当前时刻的线程快照(一般称为 threaddump 或者 javacore 文件)。线程快照就是当前 JVM 内每一条线程正在执行的方法堆栈的集合。
jstack [ option ] vmid
生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。线程出现停顿时通过 jstack 来查看各个线程的调用堆栈, 就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源。
jstack -l 3500
2010-11-19 23:11:26
Full thread dump Java HotSpot(TM) 64-Bit Server VM (17.1-b03 mixed mode):
"[ThreadPool Manager] - Idle Thread" daemon prio=6 tid=0x0000000039dd4000 nid= 0xf50 in Object.wait() [0x000000
    java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x0000000016bdcc60> (a org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor) at java.lang.Object.wait(Object.java:485)
        at org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run (Executor. java:106)
        - locked <0x0000000016bdcc60> (a org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor)
    Locked ownable synchronizers:
        - None
使用 jstack 查看线程堆栈
notion image
从 JDK 5 起,java.lang.Thread 类新增了一个 getAllStackTraces() 方法用于获取 JVM 中所有线程的 StackTraceElement 对象。使用这个方法可以通过简单的几行代码完成 jstack 的大部分功能,在实际项目中不妨调用这个方法做个管理员页面,可以随时使用浏览器来查看线程堆栈:
<%@ page import="java.util.Map"%>
<html>
<head> <title>服务器线程信息</title> </head>
<body>
<pre>
<%
    for (Map.Entry<Thread, StackTraceElement[]> stackTrace : Thread.getAllStack-Traces().entrySet()) {
        Thread thread = (Thread) stackTrace.getKey();
        StackTraceElement[] stack = (StackTraceElement[]) stackTrace.getValue();
        if (thread.equals(Thread.currentThread())) {
            continue; 
        }
        out.print("\n线程:" + thread.getName() + "\n");
        for (StackTraceElement element : stack) {
            out.print("\t"+element+"\n");
        }
    }
} %>
</pre>
</body>
</html>

3. 可视化故障处理工具

3.1 JHSDB(基于服务性代理的调试工具)

JDK 中提供了JCMD 和 JHSDB 两个集成式的多功能工具箱,它们不仅整合了上一节介绍到的所有 基础工具所能提供的专项功能,而且由于有着「后发优势」,能够做得往往比之前的老工具们更好、更强大。

3.2 JConsole(Java 监视与管理控制台)

JConsole(Java Monitoringand Management Console)是一款基于JMX(Java Manage-ment Extensions)的可视化监视、管理工具。它的主要功能是通过JMX的MBean(Managed Bean)对系统进行信息收集和参数动态调整。JMX 是一种开放性的技术,不仅可以用在虚拟机本身的管理上,还可以运行于虚拟机之上的软件中,典型的如中间件大多也基于 JMX 来实现管理与监控。虚拟机对JMX MBean的访问也是完全开放的,可以使用代码调用 API、支持 JMX 协议的管理控制台,或者其他符合 JMX 规范的软件进行访问。

3.3 VisualVM(多合-故障处理工具)

VisualVM(All-in-One Java Troubleshooting Tool)是功能最强大的运行监视和故障处理程序之一, 曾经在很长一段时间内是 Oracle 官方主力发展的虚拟机故障处理工具。Oracle 曾在 VisualVM 的软件说明中写上了「All-in-One」的字样,预示着它除了常规的运行监视、故障处理外,还将提供其他方面的能力,譬如性能分析(Profiling)。VisualVM 的性能分析功能比起 JProfiler、YourKit 等专业且收费的 Profiling 工具都不遑多让。而且相比这些第三方工具,VisualVM 还有一个很大的优点:不需要被监视的 程序基于特殊 Agent 去运行,因此它的通用性很强,对应用程序实际性能的影响也较小,使得它可以直接应用在生产环境中。这个优点是 JProfiler、YourKit 等工具无法与之媲美的。

3.4 Java Mission Control(可持续在线的监控工具)

JMC(Java Mission Control)最初是 BEA 公司的产品,因此并没有像 VisualVM 那样一开始就基于自家的 Net-Beans 平台来开发,而是选择了由 IBM 捐赠的 Eclipse RCP 作为基础框架,现在的 JMC 不仅可以下载到独立程序,更常见的是作为 Eclipse 的插件来使用。JMC 与虚拟机之间同样采取 JMX 协议进行通信,JMC 一方面作为 JMX 控制台,显示来自虚拟机 MBean 提供的数据;另一方面作为 JFR 的分析工具,展示来自 JFR 的数据。