介绍
Arthas 是Alibaba开源的Java诊断工具,可以用于线上快速定位问题。
对于我呢,常常直接用来还原事故现场。比如,异常发生时,又没有记录足够的日志。使用watch与TT排查
下载
启动
java -jar arthas-boot.jar
启动后选择要观察的java进程。
选择应用java进程:
$ $ java -jar arthas-boot.jar
*> [1]: 35542
[2]: 71560 arthas-demo.jar
Demo进程是第2个,则输入2,再输入回车/enter。Arthas会attach到目标进程上,
watch
使用watch 可以查看方法调用时的入参(params)、返回(returnObj)、异常(throwExp)
如官网用例:
通过watch命令来查看demo.MathGame#primeFactors函数的返回值:
$ watch demo.MathGame primeFactors returnObj
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 107 ms.
ts=2018-11-28 19:22:30; [cost=1.715367ms] result=null
ts=2018-11-28 19:22:31; [cost=0.185203ms] result=null
ts=2018-11-28 19:22:32; [cost=19.012416ms] result=@ArrayList[
@Integer[5],
@Integer[47],
@Integer[2675531],
]
ts=2018-11-28 19:22:33; [cost=0.311395ms] result=@ArrayList[
@Integer[2],
@Integer[5],
@Integer[317],
@Integer[503],
@Integer[887],
]
常用命令
我经常用下面的参数来排查问题, -x 可以显示属性的深度。
watch 全路径类名 方法名 "{params,returnObj,throwExp}" -x 3
参数说明
watch 的参数比较多,主要是因为它能在 4 个不同的场景观察对象
参数名称 参数说明
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
express 观察表达式
condition-express 条件表达式
[b] 在方法调用之前观察
[e] 在方法异常之后观察
[s] 在方法返回之后观察
[f] 在方法结束之后(正常返回和异常返回)观察
[E] 开启正则表达式匹配,默认为通配符匹配
[x:] 指定输出结果的属性遍历深度,默认为 1
特别说明
这里要注意方法入参和方法出参的区别,有可能在中间被修改导致前后不一致,除了 -b 事件点 params 代表方法入参外,其余事件都代表方法出参。即:如果方法中改变了params,则观察到的params可能已经被修改。
tt来回溯方法执行
有watch后,可以很方便线上的Debug。但是经常有以下场景:
- 想获取到任意对象后,执行任意方法
- watch能看到的深度不够
都可以使用tt来解决:
tt可以记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测。
案例一:找到数据库建立连接使用的url
由上图可以看出,我最终打印出了jdbc:mysql://....
找到了我想知道的url。
记录
命令:tt -t 类名 方法名
,此处-t
表示记录执行情况。 后面可以跟通配符来匹配具体的类与执行的方法。
重放
tt -t
后,web程序通过访问页面等方式最终触发到我们观察的方法,最终留下记录。如上图的1025这个index。
使用tt -i 1025 -w "target.getUrl()"
打印出了1025这次执行的目标对象(target)的getUrl
的结果。
-i
表示指定哪次记录,-w
表示执行 ognl表达式
ognl表达式支持的参数:
- target 目标对象
- params 入参
- returnObj 出参
- throwExp 异常
- …
案例二:查看更深的属性
可以通过ognl表达式,一直查看到深层次的属性。
案例三:从spring context里获取任意bean
来自:Arthas实践–获取到Spring Context,然后为所欲为
从spring context里获取任意bean
获取到spring context之后,就可以获取到任意的bean了,比如获取到helloWorldService,并调用getHelloMessage()函数:
$ tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'
@String[Hello World]
Affect(row-cnt:1) cost in 5 ms.
说明
可以使用trace帮助追踪方法调用,再使用watch,tt等命令观察。
参考
Arthas实践–获取到Spring Context,然后为所欲为
Docs » 命令列表 » tt
Docs » 快速入门