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

Arthas 3.0使用OGNL表达式求值库,详见OGNL表达式官网

常用命令

watch

函数执行数据观测

让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值抛出异常入参,通过编写 OGNL表达式进行对应变量的查看。

参数名称

参数说明

class-pattern

类名表达式匹配

method-pattern

函数名表达式匹配

express

观察表达式,默认值:{params, target, returnObj}

condition-express

条件表达式

[b]

在函数调用之前观察

[e]

在函数异常之后观察

[s]

在函数返回之后观察

[f]

在函数结束之后(正常返回和异常返回)观察

[E]

开启正则表达式匹配,默认为通配符匹配

[x:]

指定输出结果的属性遍历深度,默认为 1

观察异常信息的例子
$ watch demo.MathGame primeFactors "{params[0],throwExp}" -e -x 2
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 62 ms.
ts=2018-12-03 19:38:00; [cost=1.414993ms] result=@ArrayList[
    @Integer[-1120397038],
    java.lang.IllegalArgumentException: number is: -1120397038, need >= 2
	at demo.MathGame.primeFactors(MathGame.java:46)
	at demo.MathGame.run(MathGame.java:24)
	at demo.MathGame.main(MathGame.java:16)
,
]
  • -e表示抛出异常时才触发
  • express中,表示异常信息的变量是throwExp
按照耗时进行过滤
$ watch demo.MathGame primeFactors '{params, returnObj}' '#cost>200' -x 2
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 66 ms.
ts=2018-12-03 19:40:28; [cost=2112.168897ms] result=@ArrayList[
    @Object[][
        @Integer[1],
    ],
    @ArrayList[
        @Integer[5],
        @Integer[428379493],
    ],
]

#cost>200(单位是ms)表示只有当耗时大于200ms时才会输出,过滤掉执行时间小于200ms的调用

特别参数说明:https://arthas.aliyun.com/doc/watch.html
特殊用法:https://github.com/alibaba/arthas/issues/71

tt

方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测

  • -i: 指定特定index,查看详细信息
  • -t: 表明希望记录下类*Testprint方法的每次执行情况。
  • -n: 指定需要记录的次数,当达到记录次数时Arthas会主动中断tt命令的记录过程,避免人工操作无法停止的情况。
  • -p: 重做一次调用(replay-times指定调用次数,replay-interval指定多次调用间隔)
  • -w: 观察时空隧道使用ognl 表达式。使用表达式核心变量中所有变量作为已知条件编写表达式。

表格字段

字段解释

INDEX

时间片段记录编号,每一个编号代表着一次调用,后续tt还有很多命令都是基于此编号指定记录操作,非常重要

TIMESTAMP

方法执行的本机时间,记录了这个时间片段所发生的本机时间

COST(ms)

方法执行的耗时

IS-RET

方法是否以正常返回的形式结束

IS-EXP

方法是否以抛异常的形式结束

OBJECT

执行对象的hashCode(),注意,曾经有人误认为是对象在JVM中的内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体

CLASS

执行的类名

METHOD

执行的方法名

tt -t com.example.test.CommonInfoService updateInfo -n 5

重复INDEX为1000的调用两次,间隔时间为2000ms

tt -i 1000 -p --replay-times 2 --replay-interval 2000

sc

查看JVM已加载的类信息(scSearch-Class的简写)

参数名称

参数说明

class-pattern

类名表达式匹配

method-pattern

方法名表达式匹配

[d]

输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。如果一个类被多个ClassLoader所加载,则会出现多次

[E]

开启正则表达式匹配,默认为通配符匹配

[f]

输出当前类的成员变量信息(需要配合参数-d一起使用)

[x:]

指定输出静态变量时属性的遍历深度,默认为 0,即直接使用 toString 输出

[c:]

指定class的 ClassLoader 的 hashcode

[classLoaderClass:]

指定执行表达式的 ClassLoader 的 class name

[n:]

具有详细信息的匹配类的最大数量(默认为100)

class-pattern支持全限定名,如com.taobao.test.AAA,也支持com/taobao/test/AAA这样的格式,这样,我们从异常堆栈里面把类名拷贝过来的时候,不需要在手动把/替换为.啦。
sc 默认开启了子类匹配功能,也就是说所有当前类的子类也会被搜索出来,想要精确的匹配,请打开options disable-sub-class true开关

//获取classloader hashcode
sc -d *CommonServlet

//执行方法
ognl  -x  3 '@com.example.test.CommonInfoService@updateInfo(new com.example.test.Property())' -c [hashcode]

常用方式

Spring Context

//低版本的spring mvc
tt -t org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter invokeHandlerMethod
//高版本的spring mvc
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod

可以用tt命令的-i参数来指定index,并且用-w参数来执行ognl表达式来获取spring bean

tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'

Dubbo

在Dubbo里通过SpringExtensionFactory获取spring context,使用对应的bean
可以用tt命令的-i参数来指定index,并且用-w参数来执行ognl表达式来获取spring bean

ognl -x 1 '@org.apache.dubbo.config.spring.extension.SpringExtensionFactory@getContexts().iterator.next.getBean("userServiceImpl").findUser("aaa")'
可以用`tt`命令的`-i`参数来指定index,并且用`-w`参数来执行ognl表达式来获取spring bean

参考资料:

  1. Arthas 用户文档
  2. 当DUBBO遇上Arthas - 排查问题的实践
  3. Arthas实践–获取到Spring Context
  4. Arthas问题排查User-Case
  5. Arthas表达式核心变量