简介
给一个系统定位问题的时候,知识经验是关键基础,数据是依据,工具是运用知识处理的手段。恰当的使用虚拟机故障处理,分析工具可以提升我们分析数据,定位并解决问题的效率,当时我们也应当认识到工具永远是知识技能的一种包装,没有什么工具是‘秘密武器’,拥有了就能“包治百病”。
详情
前言
Java开发人员肯定都知道JDK 的 bin 目录中有“java.exe”、“javac.exe”这两个命令行工具,但很多人都不会主动去了解 bin 目录下其他命令行的作用。其实 bin 目录下有很多工具,包括用于虚拟机监视和故障处理的许多工具。
每逢JDK版本更新之时,bin 目录下命令行工具的数量和功能总会不知不觉的增加和增强,里面有很多工具被Sun公司作为 “礼物” 附赠给JDK的使用者,虽然在软件的使用说明中它们被称为“没有技术支持且是实验性质的”(unsupported and experimental) 的产品,但实际上,这些工具强大且稳定。bin 目录内容如下:
基础工具
一: jps :虚拟机进程状况工具
JDK提供的jps很像UNIX的ps命令,可以列出正在运行的虚拟机进程,并显示虚拟机执行的主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVMID)。虽然功能比较单一,但是他是使用频率最高的JDK命令工具,因为其他的工具大多需要输入它查询到的LVMID来确定要监控的是哪一个虚拟机进程。对于本地虚拟机进程来说,LVMID与操作系统的进程ID(Process Identifier,PID)是一致的,使用Windows的任务管理器或者UNIX的ps命令也可以查到虚拟机进程的LVMID,但如果同时启动了多个虚拟机进程,无法根据进程名称定位时,那就只能依赖jps命令显示主类的功能才能区分了。
- jps命令格式
jps [options] [hostid]
选项 | 作用 |
---|---|
-q | 只输出LVMID |
-l | 输出主类的全名 |
-m | 输出虚拟机进程启动数传递给main()函数的参数 |
-v | 输出虚拟机进程启动时JVM参数 |
- 执行样例
-l 输出主类的全名,如果进程执行的是jar包,输出jar路径
二: jstat : 虚拟机统计信息工具
jstat(JVM Statistics Monitoring Tool)是用于监视虚拟机各种运行状态信息的命令行工具.它可
以显示本地或者远程(需要远程主机提供RMI支持,Sun提供的jstatd工具可以很方便地建立远程RMI服务器)
虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形化界面,只提供纯文本控制台环
境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。
- jstat命令格式为:
jstat [options] vmid [interval [s|ms] [count]] ]
对于命令格式中的VMID与LVMID需要特别说明一下:如果是本地虚拟机进程,VMID与LVMID是一致的,如果
是与远程虚拟机进程,那VMID的格式应当是:
[protocol:][//]lvmid[@hostname[:port]/servername]
参数interval和count代表查询间隔的次数,如果省略这两个参数,说明只查询一次。假设需要每250ms查询一次进
程2764垃圾收集情况,一个查询20次,那命令应当是:
jstat -gc 2764 250 20
选项option代表着用户希望查询的虚拟机消息,主要分为3类:类装载、垃圾收集、运行期编译状况,具体选项及作用请参考下表描述。
jstat工具主要选项:
选项 | 作用 |
---|---|
-class | 监视类装载、卸载数量、总空间以及类装载所耗费的时间 |
-gc | 监视java堆状况,包括Eden区、两个survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息 |
-gccapacity | 监视内容与-gc基本相同,但输出主要关注java堆各个区域使用到的最大、最小空间 |
-gcutil | 监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比 |
-gccause | 与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因 |
-gcnew | 监视新生代GC状况 |
-gcnewcapacity | 监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间 |
-gcold | 监视老年代GC状况 |
-gcoldcapacity | 监视内容与-gcold基本相同,输出只要关注使用到的最大、最小空间 |
-gcpermcapacity | 输出永久代使用到的最大、最小空间 |
-compiler | 输出JIT编译器编译过的方法、耗时等信息 |
-printcompilation | 输出已经被JIT编译的方法 |
jstat监视选项众多,这里仅举监视一台刚刚启动的GlassFish v3服务器的内存状况的例子来演示如何查看监视结果如以下代码清单:
D:\java\jdk1.8.0_91\bin>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%的空间两个Survivor区(S0,S1表示Survivor0,Survivor1)里面都是空的。老年代(O,表示Old)和永久代(P,表示Permanent)则分别使用了
41.42%和47.20%的空间。程序运行以来共发生Minor GC(YGC,表示Yong GC)16次,总耗时0.105秒,发生Full GC(FGC,表示Full GC)3次,Full GC总耗时(FGCT,表示Full GC Time)为0.472秒,所有GC总耗时(GCT,表示GC Time)为0.577秒。
三: jinfo : Java 配置信息工具
Jinfo是JDK自带Java配置信息工具。位于java的bin目录下,jinfo的作用是实时地查看和调整虚拟机的各项参数,虽然使用Jps命令的-v参数可以查看虚拟机启动时显示指定的参数列表。但是如果想要知道没有被明确指出的系统默认值,就需要用到jinfo。
- jinfo 命令格式
jinfo [ option ] pid
四: jmap: Java 内存映像工具
jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为heapdump或者dump文件)。如果不使用jmap命令,要想获取Java堆转储快照还有一些比较“暴力”的手段:譬如用 -XX:+HeapDumpOnOutMemoryError参数,可以让虚拟机在OOM异常出现之后自动生成dump文件,通过-XX:+HeapDumpOnCtrlBreak参数则可以使用[Ctrl]+[Break]键让虚拟机生成dump文件,又或者在Linux系统下通过Kill -3命令发送进程退出信号“恐吓”一下虚拟机,也能拿到dump文件。
jmap的作用并不仅仅时为了获取dump文件,它还可以查询finalize执行队列,Java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。
和jinfo命令一样,jmap有不少功能在windwos平台下都是受限的,除了生成dump文件的-dump选项和用于查看每个类的实例、空间占用统计的-histo选项所有操作系统都提供之外,其余选项都只能在Linux/Solaris下使用。
- jmap命令格式:
jmap [option] vmid
参数 | 说明 |
---|---|
-dump | 生成Java堆转储快照。 |
-finalizerinfo | 显示在F-Queue中等待Finalizer线程执行的finalizer方法的对象。只在Linux/Solaris平台下有效 |
-heap | 显示Java堆详细信息,如使用哪种回收器、参数配置、分代状况等。只在Linux和Solaris平台下有效 |
-histo | 显示Java堆中对象统计信息,包括类、实例数量和合计容量 |
-permstat | 以ClassLoader为统计口径显示永久代内存状态。只在Linux和Solaris平台下有效 |
-F | 当虚拟机进程对-dump选项没有响应时,可使用这个选项强制生成dump快照。只在Linux和Solaris平台下有效 |
五: jhat: 虚拟机堆转储快照分析工具
Sun JDK提供jhat(JVM Heap Analysis Tool)命令与jmap搭配使用,来分析jmap生成的堆转储快照。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看。不过实事求是地说,在实际工作中,除非笔者手上真的没有别的工具可用,否则一般都不会去直接使用jhat命令来分析dump文件,主要原因有二:一是一般不会在部署应用程序的服务器上直接分析dump文件,即使可以这样做,也会尽量将dump文件复制到其他机器上进行分析,因为分析工作是一个耗时而且消耗硬件资源的过程,既然都要在其他机器进行,就没有必要受到命令行工具的限制了;另一个原因是jhat的分析功能相对来说比较简陋,后文将会介绍到的VisualVM,以及专业用于分析dump文件的Eclipse MemoryAnalyzer、IBM HeapAnalyzer 等工具,都能实现比jhat更强大更专业的分析功能。以下代码演示了使用jhat分析采用jmap生成的idea的内存快照文件。
六: jstack: Java 堆栈跟踪工具
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者等待着什么资源。
- 命令格式:
jstack [option] vmid
可视化故障处理工具
一:JHSDB : 基于服务性代理的调试工具
JHSDB是一款基于服务性代理实现的进程外调试工具。服务性代理是HotSpot虚拟机中一组用于映射Java虚拟机运行信息的,主要基于Java语言实现的API集合。
二:JConsole : Java 监视与管理控制台
(较为重要的一个工具,由于本文侧重点不同,本工具的详细解释可以在另一篇文章查看:点击进入)
JConsole 是一个内置 Java 性能分析器,可以从命令行(直接输入jconsole)或在 GUI shell (jdk\bin下打开)中运行。它用于对JVM中内存,线程和类等的监控。可使用JTop插件。它可以监控本地的jvm,也可以监控远程的jvm,也可以同时监控几个jvm。
这款工具的好处在于,占用系统资源少,而且结合Jstat,可以有效监控到java内存的变动情况,以及引起变动的原因。在项目追踪内存泄露问题时,很实用。
- 使用 JConsole 进行工作
分析器有自己的开销,因此最好的办法就是花点时间来弄清是什么开销。发现 JConsole 开销最简单的办法是,首先独自运行一个应用程序,然后在分析器下运行,并测量差异。(应用程序不能太大或者太小;我最喜欢使用 JDK 附带的 SwingSet2 样本。)因此,我使用 -verbose:gc 尝试运行 SwingSet2 来查看垃圾收集清理,然后运行同一个应用程序并将 JConsole 分析器连接到它。当 JConsole 连接好了之后,一个稳定的 GC 清理流出现,否则不会出现。这就是分析器的性能开销。
- 内存监控界面
三: VisualVM : 多合一故障处理工具
(同样重要的一个工具,由于本文侧重点不同,本工具的详细解释可以在另一篇文章查看:点击进入 )
被称为性能分析神器的VisualVM 是一款免费的,集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析,同时它还支持在 MBeans 上进行浏览和操作。本文主要介绍如何使用 VisualVM 进行性能分析及调优。
- 内存堆Heap
- CPU分析
四:Java Mission Control : 可持续在线的监控工具
JMC 是在 JAVA 7u40 发布中加入的性能监控工具。使用过 JDK 6 中 JRockit JVM 的用户并不会陌生,因为它是 Java 7 中 JMC 功能的一部分。启动 JMC 后将会显示当前机器中的所运行的 JVM 进程信息,当然我们也可以选择添加更多的 JVM 进程进行监控。图 1 中展示了使用 JMC 监控 GlassFish 应用服务器的画面。图中展示了被监控程序的基本信息,其包括 CPU 使用率和内存堆的使用率,值得注意的是,JMC 监控图中显示的是当前机器的 CPU 的使用情况,可以看到的是 JMC 监控的是整个系统,而并非只是被选中的 JVM 对 CPU 的使用情况。通过自定义设置上方仪表盘中显示的信息,既可以查看 被监控 JVM 的详细信息,例如垃圾回收,类的加载,线程的使用,以及内存堆的使用率,等等。也可以查看指定操作系统信息,例如系统的 CPU 和内存的使用率,磁盘的交换信息,平均负载等相关信息。
- Java Mission Control 监控图
JFR (Java Flight Recorder)
JFR 是 JMC 中一个非常关键的功能。它记录了 JVM 所有事件的历史数据,通过这些数据,程序性能分析人员可以结合以往的历史数据对 JVM 性能瓶颈进行分析诊断。
JFR 的基本操作是开启一系列的事件(例如,一个线程为了等待锁而被阻塞)。当某个事件发生时,这个事件的所有数据将会被保存至内存或者一个文件当中。数据流被保留在一个环形缓存中,所以只有最近发生的事件的数据才是可用的。JMC 可以从 JVM 或者文件中读取并展示这些事件数据,通过这些数据,可以进行性能分析。
通过 JVM 参数,JMC 用户界面以 jcmd 命令,可以指定上文中提到的事件类型、环形缓存的大小、数据存储的位置等信息。在默认设置下,JMC 对被监控应用的影响非常小。但是随着越来越多的事件被开启,以及触发事件的阀值的改变,JMC 的影响也在变化。接下来将展示 JFR 的用户界面。
- JFR 概述
这个例子使用 JFR 记录 GlassFish 应用服务器的 6 分钟内的相关数据。图 2 展示了 JMC 将这些数据加载之后的到总体视图。
这张图上的信息类似于 JMC 基本信息监控所看到的画面。上面的仪表盘显示的是 CPU 使用率和内存堆使用率,在其上方有一条标示事件顺序的时间轴,垂直柱状体代表事件。可以放大时间轴中感兴趣的部分进行详细分析,就像图中所示,从 6 分钟的时间轴选出位于末端的 1 分 6 秒进行放大。
CPU 使用率曲线非常清楚的看到,GlassFish 服务器所在 JVM 平均大约 70%的使用率,而机器整体的 CPU 使用率达到 100%。在最下端,有一些标签可以选择,系统属性标签,JVM 信息标签等,在画面左侧的按钮提供更加详细的应用程序运行状况。
- JFR 内存视图
JFR 内存视图收集的信息非常丰富,下图只展示了其中的一部分。从图 3 中可以看出,新生代(Young Generation) 占用的内存大小在周期性地进行有规律的波动。但有趣的是,由于没有对象需要移入老年代,应用整体的内存堆大小并没有增长。左下角面板中展示在监控期间所有类型的垃圾回收事件,在本例中一直为 ParallelScavenge。当选中一个事件时,右下角将更加细化的显示此事件,包括此事件的所有阶段以及每个阶段的时间消耗。
从图中各种各样的标签可以看到包含了丰富的信息,其中包括引用对象被清理的时间和数量,并发回收器中是否有 Promotion 失败或者 Evacuation 失败,垃圾回收器自身算法的配置,等等信息。
- JFR 代码视图
JFR 代码视图展示了从记录的数据中获得的基础分析信息。如图 4 所示,第一个标签页显示了所有的包名,在其他分析工具我们并没见过类似的功能。可以看出图中使用 Java.Math 方法的执行占应用程序所有方法调用运行总时长的比重为 41%。传统的分析视角位于底部,例如热点方法和被分析代码的调用如下图所示。
通过左侧面板的过滤器可以过滤显示的事件,在图中,只选择了应用级的事件。需要注意的是,只有在 JFR 记录保存事件中指定的事件类型才会出现在这里,在这里只能在此基础上进行过滤。
JFR 目前支持 77 种事件类型,大多数类型的事件为周期性事件,每隔固定时间将会产生一次,其他类型的事件为触发型,只有当达到某种设定的阀值后被触发,也就是说才会被 JFR 发现并监控起来。
总结
名称 | 主要作用 |
---|---|
jps | JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程 |
jstat | JVM Statistics Monitoring Tool,用于收集HotSpot虚拟机各方面的运行数据 |
jinfo | Configuration Info for Java,显示虚拟机配置信息 |
jmap | Memory Map for Java,生成虚拟机的内存转储快照(heapDump文件) |
jhat | JVM Heap Dump Browser,用于分析heapDump文件,它会建立一个HTTP/HTML服务器,让用户可以在浏览器上查看分析结果 |
jstack | Stack Trace for Java,显示虚拟机的线程快照 |
JHSDB | JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程 |
jconsole | Java Monitoring and Management Console,是一种基于JMX的可视化监视、管理工具,将上面提到的几种工具功能集合在可视化页面上。启动界面相当于jps功能,可直接手动选择系统内的虚拟机进程;共有“概述”、“内存”、“线程”、“类”、“VM摘要”、“MBean”留个标签页, 每个标签页监视不同的内容,例如“内存”页相当可视化的jstat工具。 |
jvisualvm | All-in-One Java Troubleshooting Tool,多合一故障处理器,是目前为止JDK发布的功能最强大的运行监视和故障处理程序,它使用的插件化、可视化的实现方式,用户可以点击“工具—插件菜单”,在有网络的环境下下载所需的插件使用,除此之外还提供了许多的功能,比如性能分析(Profiling),甚至比JProfiler等专业收费的工具都不会逊色。也可以在可视化界面直接生成Dump快照文件,并对其进行浏览。-----在VisualVM中生成Dump快照文件有两种方式:(1)在“应用程序”窗口中右键点击应用程序节点,然后选择“堆Dump”;(2)在“应用程序”窗口中双击应用程序节点以打开应用程序标签,然后在“监视”标签中点击“堆Dump”。 |
Java Mission Control | JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程 |
最终:
本文介绍了随JDK发布的6个命令行工具与4个可视化的故障处理工具,灵活使用这些工具,可以为处理问题带来很大的便利。
参考资料 & 致谢
【1】深入理解Java虚拟机 - 第三版 周志明
【2】JConsole可视化工具介绍
【3】性能能分析神器VisualVM
【3】Java 性能分析工具 , 第 3 部分: Java Mission Control