我们在开发中不难出现这样的问题:线上某个功能不可用,登上机器查看日志,发现在报错。但为什么报错,翻了半天日志可能也没找到原因,“日志”到用时方恨少,非常后悔当时没有多打日志。
此时,要么选择在线 Debug — 有时候并不那么容易;要么修改代码,增加相关日志打印语句,重新发布部署,而这容易导致问题难以复现。
Arthas 的出现解决了这样的困境。
Arthas(阿尔萨斯),它是由阿里开源的一款 Java 诊断工具,继承自 BTace 和 Greys,提供了 :
- 系统环境信息、虚拟机信息: (线程信息、内存信息、类加载信息)等的查看、监控。
- 运行时查看方法执行详情、方法调用链、方法调用统计信息。
- 提供内存中编译类、反编译加载的类、热加载类等功能
更多详细功能请到官方网站查看。
本系列文章的目的
Arthas 中文文档写的十分详尽,此处不再做文档的搬运工。文章主要是对其做一些归类总结
在阅读下面的内容之前,请先了解 官方命令列表
命令分类
使用 Arthas的第一步就是,熟练运用相关命令,活用相关命令,在真正出现线上问题,排查问题才能行云流水,一气呵成。下面对命令按照使用场景进行了分类分为:
公共工具:sc、sm、stack
线上异常排查:watch、tt
动态代码执行: ognl
热更新: jad、mc、redefine、classloader、dump
性能分析:jvm、trace、thread
彩蛋::july、thanks
公共工具
用于查找类、方法、方法调用栈。大多数命令使用前都需要知道类和方法,这些公共的工具提供了快速定位目标的方法(通过通配符或者正则表达式)
线上异常排查
线上排查问题的流程一般是:
查看日志,找到具体报错异常栈和报错位置,也可以使用 sc,sm,stack 等工具找到方法调用入口,再使用 tt 或者 watch -e 查看异常栈和报错位置
查看方法调用细节,洞悉方法执行现场。
有两个选择:使用tt (TimeTunnel 时空隧道),使用 watch
tt 命令
可以保存当前方法调用的详细信息,包括入参、返回值、异常信息(如果有的话),方便快速定位。也可以重放调用(但是不一定准确)
watch 命令
观察某个方法的详情,具体信息可以在后面跟表达式指定。例如:
watch demo.MathGame primeFactors "{params,returnObj}"
可以查看参数,返回值。如何选择:
tt 可以保存多个方法调用现场,方便后续查看、重放。但是有时候查看、重放不一定准确,原因是tt 只是保存当时环境的对象引用,当对象值改变之后,你查看的时候看到的是最新的值,而不是当时调用的值,这时,需要使用 watch 命令准确的查看方法调用的现场
动态代码执行
上一步的异常排查发现出错位置和原因,如果仍然不知道如何修改,需要做一些探索,就需要动态代码执行工具了。Arthas 通过 ognl 表达式查看一些静态字段值,执行一些代码片段等。注意,getstatic 可以替代 ognl 查看类的静态字段的功能,但不建议学习,增加学习成本。
热更新
动态代码执行适合于执行一些表达式类短小精悍代码,对于大段代码就显得力不从心。于是就需要热更新技术了。
热更新工具箱包括 jad、mc、redefine、classloader、dump。热更新一段代码一般遵循一些顺序:
- 反编译:使用jad 反编译已经加载的字节码,如果觉得反编译效果不好,可以使用 dump 转储字节码文件,然后使用其他工具反编译为代码。
- 修改代码:修改想要更新的代码
- 编译:可以使用 mc 命令编译更新的代码(需要指定class loader),也可以使用 idea 等第三方工具编译好,上传到服务器
- 加载新的类:使用 redfine 命令加载
redefine 使用限制:
- 不支持新增属性、方法
- 正在运行的函数 redefine 后不会生效,只有方法运行完后下次运行才会生效。
使用技巧
匹配多个方法
如果想匹配多个方法,可以使用正则表达式,命令后面添加 -E 开启:
1 |
|
退出 Arthas
使用 exit/quit 命令结束当前回话,关闭客户端,但不会关闭服务端。使用 jps 查看,会看到Arthas 还在运行。需要使用 shutdown 命令完全关闭服务端。