JVM工具实战:线上问题排查与性能分析

438 阅读5分钟

今天我们来聊聊如何使用 JVM 工具排查线上问题,在程序运行过程中,我们可能会遇到各种问题,而稳定性风险是我们无法回避的一个话题。由于代码质量不佳或架构设计上的缺陷,JVM 层面的风险主要表现为内存溢出和死锁等问题,常见的异常包括 OOM 和 CPU 使用率急剧上升。为了深入了解问题的根本原因,我们需要熟练掌握 JVM 工具的使用。幸运的是,JVM 已经为我们提供了一系列的诊断工具。今天,我会带你熟悉 JVM 的一些常见诊断工具。

jps:虚拟机进程状况工具方式

首先,我们来看 jps 这个工具,它可以列出当前正在运行的 Java 虚拟机进程,jps 可以显示虚拟机执行的主类以及进程的虚拟机 ID“LVMID”。jps 是我们使用频率最高的工具,其他工具都需要依赖 jps 查询到的 LVMID 来进行下一步操作。下面我们看一下 jps 的命令格式:

jps [option] [hostid]

我们来看一下 jps -l 这个例子,前一列是查询到的 LVMID,后一列是主类的全名。

图片

下面的列表是 jps 一些选项的作用,你可以自己在服务上敲一下命令试试。

图片

jstat:虚拟机统计信息监视工具

我们现在已经知道了 jps 就可以获取 LVMID,那有了这个 LVMID,我们可以做什么呢?

我们先来看一个高频的命令——jstat,它可以监控 JVM 中的多种统计信息,包括类加载信息、内存使用情况、垃圾回收情况以及即时编译器(JIT)的信息。jstat 的命令格式如下:

jstat [option vmid [interval [s|ms] [count] ] ]

其中 interval 是查询的间隔时间,count 是查询的次数。我们来看一下 jstat -gc 16400 200 3 这个例子,代表每 200 毫秒执行一次 jstat -gc 命令,连续执行 3 次。

图片

我们再来了解一下查询出的这几个参数的含义:

  • S0、S1:Survivor0、Survivor1 幸存者区

  • E:新生代区

  • O:老年区

  • P:永久代

  • YGC:MinorGC

  • YGCT:MinorGC 的耗时

  • FGC:FullGC

  • FGCT:FullGC 总耗时

  • GCT:GCTime,意思是 GC 总耗时

下面的列表是 jstat 一些选项的作用,你可以自己在服务上敲一下命令试试。

图片

jinfo:Java 配置信息工具

接着是 jinfo 工具,它可以用来查看和调整 JVM 的配置参数。使用 jps 的-v选项可以查看 JVM 启动时显式指定的参数,而 jinfo 的-flag选项可以帮助我们查看那些使用了默认值的参数。更强大的是,jinfo 甚至可以在运行时修改这些参数。jinfo 的命令格式如下:

jinfo [option] pid

我们再来看一下 jinfo -flag 的例子,查询 CMSInitiatingOccupancyFraction 参数的值:

jinfo -flag CMSInitiatingOccupancyFraction 1444
-XX: CMSInitiatingOccupancyFraction85

jmap:Java 内存映像工具

接下来是 jmap 工具,它用于创建 Java 堆内存的快照,也就是我们常说的"dump 文件",生成的 dump 文件对于分析内存溢出问题非常有用。jmap 不仅可以获取 dump 文件,还可以查询永久代、堆空间的使用情况和垃圾收集器的信息。jmap 的命令格式如下:

jmap [option] vmid

再来了解一下具体的 option 选项的作用:

图片

看完上述 option 选项的作用,接下来我们看一个使用 jmap 生成一个 dump 文件的例子:

图片

通过上述例子我们对 jmap 有了更深的了解,下面我们继续看虚拟机堆转储快照分析工具——jhat。

jhat:虚拟机堆转储快照分析工具

jmap 有一个搭档叫 jhat,jhat 可以分析 jmap 生成的堆转储快照。jhat 生成的 dump 文件结果报告可以直接在浏览器中打开。不过 jhat 的分析功能相对来说比较简单,因此我们通常不会直接使用 jhat 来分析 dump 文件,此外要注意分析工作是一个耗时耗力的过程,所以不要在生产环境服务器上分析 dump 文件。后续我们会介绍更专业的分析工具,可以实现比 jhat 更专业的分析功能。

我们先来看一下使用 jhat 分析 dump 文件的例子:

图片

根据提示在浏览器中输入 http://localhost:7000 就可以看到分析结果。

图片

通过上述例子,我们可以看到分析结果以包为单位来分组显示,每个包都可以点进去看到更详细的分析,从而看到各种对象的空间占比,排查问题还是很方便的。你也可以自己尝试一下。

jstack:Java 堆栈跟踪工具

下面我们介绍最后一个命令 jstack,这个工具使用频率也很高,jstack 用于生成虚拟机当前时刻的线程快照,也就是“线程 dump”文件。线程快照的意思就是线程当前的堆栈信息,生成线程快照的主要目的通常是为了定位线程阻塞的原因,如死循环、死锁、IO 资源问题等。如果发生线程阻塞,我们可以使用 jstack 来查看线程堆栈,就可以清晰地看到这些线程在后台执行什么任务、wait 什么 IO 资源。

我们来看一下 jstack 的命令格式:

jstack [option] vmid

我们使用 jstack -l 16400 查看线程堆栈。

图片

下面的列表是 jstack 具体选项的作用,你可以自己在服务上敲一下命令试试。

图片

总结

们今天介绍了 JVM 自带的一系列常用工具,每个工具都有其独特的功能和用途。在遇到线上问题时,我们可以先使用 jps 查询进程的虚拟机 ID,如果是线程问题可以使用 jstack,如果是内存问题可以使用 jmap 和 jhat,而 jstat 和 jinfo 则可以帮助我们在问题发生前监控内存的使用情况和配置信息。当然,这些工具的基本使用方法还有很多细节,需要通过实践来完全掌握。

图片