Arthas使用指南

2,864 阅读3分钟
是什么

Arthas是Alibaba开源的Java诊断利器,可以帮助开发人员在不修改代码或重启服务器的情况下快速定位线上问题。它采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:

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

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

Github: github.com/alibaba/art…

文档:arthas.aliyun.com/doc/

快速入门
下载并启动demo
下载已经打包好的arthas-demo.jar 
curl -O https://alibaba.github.io/arthas/arthas-demo.jar 
在命令行下执行 
java -jar arthas-demo.jar
启动arthas
  1. 因为arthas-demo.jar进程打开了一个窗口,所以另开一个命令窗口执行arthas-boot.jar
  2. 选择要粘附的进程:arthas-demo.jar

image.png image.png

dashboard仪表板

输入dashboard(仪表板),按 回车/enter ,会展示当前进程的信息,按 ctrl+c 可以中断执行。

image.png 1.第一部分是显示JVM中运行的所有线程:所在线程组,优先级,线程的状态,CPU的占用率,是否是后台进程等

  1. 第二部分显示的JVM内存的使用情况

  2. 第三部分是操作系统的一些信息和Java版本号

如果只想查看线程信息可以输入thread,后面跟上线程id可以查看具体线程信息

jad反编译

通过解压jar包发现demo包下有一个MathGame.class

image.png 执行下面命令

jad demo.MathGame

image.png

watch命令

通过watch命令来查看 demo.MathGame#primeFactors 函数的返回值:

$ watch demo.MathGame primeFactors returnObj
退出arthas

如果只是退出当前的连接,可以用 quit 或者 exit 命令。Attach到目标进程上的arthas还会继续运行,端口会保持开放,下次连接时可以直接连接上。

如果想完全退出arthas,可以执行 stop 命令。

常用命令详解
watch命令

watch 让你能方便地观察到指定方法的调用情况。能观察到的范围为:

返回值、抛出异常、入参(还能观察执行函数的对象本身,通过编写 OGNL 表达式进行对应变量的查看。

特别说明

  • watch 命令定义了4个观察事件点,即 -b 方法调用前, -e 方法异常后, -s 方法返回后, -f 方法结束后
  • 4个观察事件点 -b 、 -e 、 -s 默认关闭, -f 默认打开,当指定观察点被打开后,在相应事件点会对观察表达式进行求值并输出
  • 这里要注意 方法入参 和 方法出参 的区别,有可能在中间被修改导致前后不一致,除了 -b 事件点params 代表方法入参外,其余事件都代表方法出参
  • 当使用 -b 时,由于观察事件点是在方法调用前,此时返回值或异常均不存在
  1. 观察方法返回结果 returnObj

使用方式看着复杂,其实很简单。来个最简单的示例: 假设我们要观察下面这段代码中字符串的 contains 方法。

public class App {
    public static void main(String[] args) throws IOException {
        String hello = "Hello Arthas";
        while (true) {
            boolean contains = StringUtils.contains(hello, "Arthas");
            System.out.println(contains);
        }
    }
}

可以使用如下语句:

$ watch org.apache.commons.lang3.StringUtils contains returnObj -n 3

-n 3 表示只执行三次,这参数挺常用,不然很容易被输出刷屏。

2.观察demo.MathGame类中primeFactors方法出参和返回值,结果属性遍历深度为2。

params表示所有参数数组,returnObject表示返回值 
watch demo.MathGame primeFactors "{params,returnObj}" -x 2

3.观察当前对象中的属性

使用target.field_name访问当前对象的某个属性 
watch demo.MathGame primeFactors 'target.illegalArgumentCount'
trace命令

作用

查看方法内部调用路径,并输出方法路径上的每个节点上耗时

语法

trace 类全限定名 方法名

举例

trace demo.MathGame run

如果方法调用的次数很多,那么可以用-n参数指定捕捉结果的次数。

比如下面的例子里,捕捉到一次调用 就退出命令。

trace demo.MathGame run -n 1

默认情况下,trace不会包含jdk里的函数调用,如果希望trace jdk里的函数,需要显式设置-- skipJDKMethod false。

trace --skipJDKMethod false demo.MathGame run

据调用耗时过滤,trace大于0.5ms的调用路径

trace demo.MathGame run '#cost > .5'
热更新

本篇主要是介绍 jad / mc / redefine 这三个命令的配合使用,以达到热更新代码的目的 运行arthas自带的demo包

java -jar arthas-demo.jar

启动Arthas服务

java -jar arthas-boot.jar

使用jad反编译demo.MathGame输出到/tmp/MathGame.java

jad --source-only MathGame > /tmp/MathGame.java

--source-only选项,可以只打印源代码。

该命令其实很实用,可以查看线上运行的代码是不是自己想要部署的代码

修改 /tmp的MathGame.java文件,增加一个打印信息

这边有几个限制

  • 不允许新增加field/method
  • 正在跑的函数,没有退出不能生效,比如下面新增加的 System.out.println ,只有 run() 函数里的会生效

image.png

mc内存编译代码。将保存好的MathGame.java文件编译成class文件

mc /tmp/MathGame.java -d /tmp

redefine重新加载编译好的.class文件:

redefine /tmp/demo/MathGame.class

效果如下

image.png