arthas 监控诊断工具

世界上基本不存在没有Bug的程序,关键点是如何快速定位解决问题。Arthas是国内阿里巴巴开源的一款JVM线上监控诊断工具,它的功能非常全面,包括线程内存GC等基础信息监控、方法执行监控、火焰图生成等,甚至还提供了直接热更新类字节码这种逆天操作,这些功能都是从开发团队的实战经验中总结形成的,它们用起来让人爱不释手,对线上问题排查很有帮助。相比于JDK自带的各种命令,Arthas功能更强大更实用,解决问题效率也更高。

官方网站:https://arthas.aliyun.com/

Github:https://github.com/alibaba/arthas

Arthas工具安装运行

Arthas工具安装非常简单,我们直接在Github的Releases页面找到压缩包下载即可。压缩中中包含了Arthas程序的Jar包,我们可以使用java -jar命令直接运行。

java -jar arthas-boot.jar

运行成功后,根据提示选择JVM进程,即可将Arthas附加到要监控的应用上了。

我们可以输入help查看可用的命令和帮助信息,如果需要退出Arthas的Shell,输入exitquit即可。

查看dashboard

在Arthas的Shell中输入dashboard即可查看Dashboard监控面板。

在监控面板中,我们可以看到程序中的各个JVM线程状态、各个分区内存和JVM运行时的相关信息。

堆转储

我们输入以下命令可以将堆内存转储。

heapdump /tmp/dump.hprof

如果仅希望转储live对象,可以使用--live参数。

heapdump --live /tmp/dump.hprof

监控方法执行信息

线上工程一旦出现报错等情况,代码中也没有打印更多的日志,我们通常又不可以直接打断点(这样会造成程序阻塞),此时调试起来就比较困难了。Arthas提供了监控方法执行情况的功能,我们可以在方法执行前中后期和抛出异常时查看相关信息,下面是一个具体使用例子。

watch com.gacfox.demo.controller.TradingController getTradingPage '{params,returnObj,target,throwExp}' -x 2

这里假设我们监控的是com.gacfox.demo.controller.TradingController类的getTradingPage方法,后面的'{params,returnObj,target,throwExp}'是监控的具体内容:

  • params:入参监控
  • returnObj:返回参数监控
  • target:对象监控,会输出对象中的成员变量等信息
  • throwExp:异常信息监控

-x参数用于指定输出内容对于对象的遍历深度,我们这里将其指定为2

上面例子命令的监控情况如下图(这里我们手动触发了一个方法执行)。

从图中我们可以看到方法的入参、返回值和对象信息,由于没有报错,因此异常信息为null

监控方法执行耗时

Arthas中,我们可以使用类似如下命令查看方法的执行耗时。

trace com.gacfox.demo.controller.TradingController getTradingPage

这里假设我们监控的是com.gacfox.demo.controller.TradingController类的getTradingPage方法,例子命令的监控情况如下图(这里我们手动触发了一个方法执行)。

从输出信息中可以看出我们的方法执行耗时0.186664ms。

生成火焰图

火焰图是一种可视化性能分析图表,在Java程序性能调优领域,火焰图通常用于展示方法调用的时间分布情况,以帮助开发人员识别应用程序中的性能瓶颈。Arthas工具能够很方便的生成火焰图,使用方法如下。

开始采样:

profiler start

结束采样并生成报告:

profiler stop --format html

根据输出提示,我们可以找到输出的火焰图HTML文件。

火焰图的横轴表示时间,纵轴表示方法调用栈,每个矩形块代表一个方法调用,矩形的宽度表示该方法在整个时间范围内的执行时间,而矩形的垂直位置表示调用栈的深度。因此火焰图从顶部到底部的方向可以看出方法的调用层次,而每个矩形的宽度则反映了方法的执行时间。通过观察火焰图,开发人员可以快速定位到执行时间较长的方法和调用链,并深入分析这些部分的性能问题,例如是否存在不必要的方法调用、是否存在耗时较长的方法等,这样就可以有针对性地进行性能优化,提高应用程序的响应速度和整体性能。

查看类信息

Arthas中,我们可以查看一个类的各种信息,甚至还能直接查看反编译代码,对于定位那些源码不明的类文件存在的问题很有帮助,下面例子我们查看了TradingController类的信息。

sc -d -f com.gacfox.demo.controller.TradingController
  • -d:输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、ClassLoader等详细信息。
  • -f:输出当前类的成员变量信息,需要配合-d使用

输出内容如下。

sc命令支持模糊匹配,例如使用sc -d -f com.gacfox.demo.*也是可以的。

此外,我们还可以使用jad命令将类直接反编译。

jad com.gacfox.demo.controller.TradingController

输出内容如下。

修改logger

Arthas有个很实用的功能,它能修改应用的日志级别。例如我们的线上程序将日志配置为了INFO级别,然而发生问题时我们需要查看DEBUG日志,但我们又不方便重启服务,因为那样会造成服务中断,此时我们可以用Arthas将日志级别临时改成DEBUG,该操作支持大部分常见的日志框架。

在Arthas的Shell中输入logger命令,我们会看到类似如下输出。

输出中包含了logger名字、其类加载器、日志级别等信息。

输入以下命令,可以将上图中名为ROOTlogger日志级别改为DEBUG。

logger -c 2b71fc7e --name ROOT --level DEBUG

这里我们使用-c参数指定了类加载器的哈希值,这是因为Arthas操作字节码时默认使用SystemClassloader,但SpringBoot工程有些不同,SpringBoot使用自定义的类加载器,因此我们需要额外指定该参数,一些其它的Java工程类型或框架可能也有类似的情况。

热替换class

Arthas能够直接加载并热替换.class文件,该替换是进程内一直有效的,不受Arthas退出影响,假设我们要替换TradingController.class这个文件,可以执行如下命令。

retransform /home/ubuntu/TradingController.class

其中,TradingController.class是我们修改代码后再本地进行了编译并上传到了服务器上。

retransform命令的一些限制:

  • 不允许增加新的成员变量和方法
  • 正在执行的方法没有退出不能生效
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。