【JVM系列读书笔记】三、JVM性能监控与故障处理

190 阅读8分钟

注:本文主要参考《深入理解Java虚拟机 第2版》

1、概述

在实际工作过程中,我们经常会遇见线上的一些问题,比如程序规律的卡顿、运行一段时间后内存溢出导致程序挂掉等现象。这些现象都是由于我们代码编写问题导致的,线下测试由于运行时间不够长,或者并发量不足没有及时发现,当线上出现事故后需要快速处理,这时候就需要使用合适的工具快速定位,来解决问题。同时对于刚上线的代码,我们也可以使用合适的工具对程序进行监控,发现问题后,及时解决。

2、JDK自带工具

2.1、JDK命令行工具

生产环境的机器出现问题后,通过远程工具连接可能会受到一些限制,使用命令行工具可以登录上去进行故障处理,常用的命令行工具如下:

  1. 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参数
  2. 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基本相同,输出主要关注使用到的最大、最小空间
  3. jinfo, Configuration Info for Java,实时地查看和调整虚拟机各项参数:

    • 命令格式:jinfo [option] pid;
    • 选项(options)如下表所示:
      选项作用
      -v查看虚拟机启动时显式指定的参数列表
      -flag查看未被显示的指定参数的系统默认值,使用java -XX:-PrintFlagsFinal也可以
      -sysprops把虚拟机进程的System.getProperties()的内容打印出来
      -flag[+-] name 或者 -flag name=value可以修改一部分运行期科协的虚拟机参数
  4. 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文件;
      • dump文件的分析工具\color{red}{dump文件的分析工具}
  5. jhat,JVM Heap Analysis Tool,是Sun SDK提供的jhat命令与jmap搭配使用,其内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看,不过分析还是比较耗资源,如果有其他工具,尽量使用其他工具,不然Eclipse MAT、IBM HeapAnalyzer等工具;

  6. 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中首次发布的,现在是主力推动的多合一故障处理器;

  1. Jconsole,Java Monitoring and Management Console,是一种基于JMX的可视化监视管理工具,通过JDK/bin目录下的jconsole.exe启动,主要功能如下:
    • 内存监控,相当于可视化的jstat命令,用于监视受收集器管理的虚拟机内存(Java对和永久代)的趋势变化;
    • 线程监控,相当于可视化的jstack命令,遇到线程停顿,可以使用此功能进行监控分析;
  2. 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.aliyun.com/doc/

当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:

  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  5. 是否有一个全局视角来查看系统的运行状况?
  6. 有什么办法可以监控到JVM的实时运行状态?
  7. 怎么快速定位应用的热点,生成火焰图?

Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

4、小结

再知道JVM工具原理后,以及知道这么多工具,我们可以在工作过程中可以将这些工具方法使用上,让我们告别996。

后续会分分享一些实战问题。