注:本文主要参考《深入理解Java虚拟机 第2版》
1、概述
在实际工作过程中,我们经常会遇见线上的一些问题,比如程序规律的卡顿、运行一段时间后内存溢出导致程序挂掉等现象。这些现象都是由于我们代码编写问题导致的,线下测试由于运行时间不够长,或者并发量不足没有及时发现,当线上出现事故后需要快速处理,这时候就需要使用合适的工具快速定位,来解决问题。同时对于刚上线的代码,我们也可以使用合适的工具对程序进行监控,发现问题后,及时解决。
2、JDK自带工具
2.1、JDK命令行工具
生产环境的机器出现问题后,通过远程工具连接可能会受到一些限制,使用命令行工具可以登录上去进行故障处理,常用的命令行工具如下:
-
jps,JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程:
- 命令格式:jps [ options ] [ hostid ]
- hostid:jps可以通过RMI协议开启了RMI服务的远程虚拟进程状态,hostid为RMI注册表中注册的主机名;
- 选项(options)如下表所示:
选项 作用 -q 只输出LVMID(Local Virtual Machine Identifier,本地虚拟机唯一id) -m 输出虚拟机进程启动时传递给主类main()函数的参数 -l 输出主类的全名,如果进程执行的是Jar包,输出Jar路径 -v 输出虚拟机进程启动时JVM参数
-
jstat,JVM Statistics Monitoring Tool,用于监控虚拟机各种运行状态信息的命令行工具,可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据:
- 命令格式:jstat [option vmid [interval[s|ms]] [count]]]
- 本地虚拟机进程,vmid和LVMID一样;
- 远程虚拟机进程,格式:[protocol:][//]lvmid[@hostname[:port]]/servername]
- intervals和count表示间隔时间与次数,默认只查询一次;
- 选项(options)如下表所示:
选项 作用 -class 监视类装载、卸载数量、总空间以及类装载所耗时间 -gc 监视Java堆状况,包括Eden区、两个survivor区,老年代、永久代等的容量,已用空间、GC时间合集等信息 -gccapacity 监视内容与-gc基本相同,但输出主要关注Java堆各区使用到的最大、最小空间 -gcutil 监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比 -gcnew 监视新生代GC状况 gcnewcapacity 监视内容no关于-gcnew基本相同,输出主要关注使用到的最大、最小空间
- 命令格式:jstat [option vmid [interval[s|ms]] [count]]]
-
jinfo, Configuration Info for Java,实时地查看和调整虚拟机各项参数:
- 命令格式:jinfo [option] pid;
- 选项(options)如下表所示:
选项 作用 -v 查看虚拟机启动时显式指定的参数列表 -flag 查看未被显示的指定参数的系统默认值,使用java -XX:-PrintFlagsFinal也可以 -sysprops 把虚拟机进程的System.getProperties()的内容打印出来 -flag[+ -] name 或者 -flag name=value 可以修改一部分运行期科协的虚拟机参数
-
jmap, Memory Map for Java,用于生成堆转储快照(heapdump或者dump文件):
-
命令格式:jmap [option] vimd,示例:jmap -dump:format=b,file=dump-info.bin 6131;
-
选项(options)如下表所示:
选项 作用 -dump 生成Java对转储快照,格式为:-dump:[live, ]format=b, file=,其中live子参数说明是否只dump出存活的对象 -finalizerinfo 显示在F-Queue中等待Finalizer线程执行finalize方法的对象,只在Linux、Solaris平台下有效 -heap 显示Java堆纤细信息,如使用哪种回收器、参数配置、分代状况等。只在Linux/Solaris平台下有效 -histo 显示堆中对象统计信息,包括类、实例数量、合集容量 -permstat 以ClassLoader为统计口径显示永久化内存状态,只在Linux/Solaris平台下有效 -F 当虚拟机进程对-dump选项没有响应时,可使用这个选项强制生成dump快照,只在Linux/Solaris平台下有效 - 其他生成dump文件的方法:
- -XX:+HeapDumpOnOutOfMemoryError参数,可以让虚拟机在出现OOM异常后自动生成dump文件
- -XX:+HeapDumpOnCtrlBreak参数,可以使用[Ctrl]+[Break]键让虚拟机生成dump文件;
- Linux系统下,通过kill -3 命令发送退出信号,从而得到dump文件;
- :
- Eclipse的MAT插件,下载地址:download.eclipse.org/mat/1.6/upd…
- IBM HeapAnalyzer,下载地址:www.ibm.com/support/pag…
- jhat,见下个工具介绍;
- 其他生成dump文件的方法:
-
-
jhat,JVM Heap Analysis Tool,是Sun SDK提供的jhat命令与jmap搭配使用,其内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看,不过分析还是比较耗资源,如果有其他工具,尽量使用其他工具,不然Eclipse MAT、IBM HeapAnalyzer等工具;
-
jstack,Stack Trace for Java,用于生产虚拟机当前时刻的线程快照,一般称为threaddump或者javacore文件,线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈集合,生产线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁,死循环,请求外部资源导致的长时间等待等原因:
- 命令格式:jstack [ option ] vmid,示例:jstack -l 6131 > stack.txt;
- 选项(options)如下表所示:
选项 作用 -F 当正常输出的请求不被响应时,强制输出线程堆栈 -l 除对现场外海峡是关于锁的附加信息 -m 如果调用到本地方法的话,可以显示C/C++的堆栈
2.2 JDK的可视化工具
JDK除了提供大量的命令行工具外,还提供了两个强大的工具,JConsole和VisualVM,其中Jconsole是JDK1.5时就提供了的虚拟机监控工具,而VisualVM是在1.6 Update7中首次发布的,现在是主力推动的多合一故障处理器;
- Jconsole,Java Monitoring and Management Console,是一种基于JMX的可视化监视管理工具,通过JDK/bin目录下的jconsole.exe启动,主要功能如下:
- 内存监控,相当于可视化的jstat命令,用于监视受收集器管理的虚拟机内存(Java对和永久代)的趋势变化;
- 线程监控,相当于可视化的jstack命令,遇到线程停顿,可以使用此功能进行监控分析;
- VisualVM,All-in-One Java Troubleshooting Tool,除了本地功能,还可以通过安装插件来拓展,具有如下功能:
-
显示虚拟机进程以及进程的配置,环境信息(jsp,jinfo);
-
监视应用程序CPU、GC、堆、方法区、以及线程的信息(jstat、jstack);
-
dump以及分析堆转储快照(jmap,jhat);
-
方法级的程序运行性能分析,找出被调用最多、运行时间最长的方法;
-
离线程序快照,手机程序的运行配置、线程dump、内存dump等信息建立一个快照,可以将快照发送开发者处进行Bug反馈;
-
其他plugins的无限可能性;
-
特色功能如下:
- 生成,浏览堆转储快照,右键选择"应用程序",选择堆Dump,可以另存为Dump文件,可以选择装入立项的Dump文件;
- 分析程序性能,在JProfiler标签页(需要安装插件)中,然后在CPU方面可以对每个方法的执行次数、执行耗时,以及内存方面每个方法关联的对象数以及这些对象所占的空间;
- BTrace动态日志跟踪,作用是在不停止目标程序运行的情况下,通过HotSpot虚拟机的HotSwap技术动态加入原本并不存在的调试代码,此功能较为强大,可以进一步了解;
-
2.3 神器 - Arthas
由于VisualVM远程连接比较麻烦,而命令行的All in One工具没有,零散使用自带的命令行工具比较麻烦,因此Arthas出现了,Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。
当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。
4、小结
再知道JVM工具原理后,以及知道这么多工具,我们可以在工作过程中可以将这些工具方法使用上,让我们告别996。
后续会分分享一些实战问题。