十分钟学习一个日常定位bug技巧之Arthas工具
你独处的能力,决定了你的人生高度你定位BUG的能力,决定了你的薪资高度-收录于《胡说八道全集》
平常编码工作中,我们会常遇到如下场景:本地运行没问题,但测试环境就是运行异常,棘手的是,看日志一切都是正常的。
遇到这种情况,常见的做法是到测试环境把class文件拉回本地反编译,比对测试环境代码是否部署有问题。
如果代码没问题,则添加打印参数的日志,再重新部署,再复现。这种方法可以解决问题,但一系列的操作,还是太费时间。
这里介绍一个工具Arthas
,它可以直接在运行中的服务把JVM中的class字节码反编译,修改反编译后的代码,再直接重新发布到JVM中,整个过程,不用重启服务。
下面介绍整个过程,目录如下:
- 运行Arthas
- 反编译class字节码
- 修改代码
- 发布到JVM
以Arthas官网的Demo为例:
下载Arthas:https://github.com/alibaba/arthas/releases
运行Demo程序,java -jar math-game.jar
。这是一个每隔一秒通过Random获取随机数,然后做质因数分解,并打印出分解结果的小程序
运行Arthas,java -jar arthas-boot.jar
运行后,arthas会打印出当前所有的Java进程,根据中括号中的ID选择要处理的进程。如,输入1,然后按ENTER
这时候,arthas已经attach上前面运行的math-game程序。main_class也显示了该程序的主类
我们以这个demo.MathGame为例,反编译它jad demo.MathGame
如上图,可见反编译后的main函数为一个死循环,每隔一秒运行一次run函数。
我们把反编译后的代码存到本地jad demo.MathGame --source-only --lineNumber false > MathGame.java
,这样,在运行arthas的目录下就生成了MathGame.java文件。
我们编辑它,在它run函数中加一个打印语句System.out.println("动态加的代码,打印number值为:" + number)
加了代码后,我们可以自己用javac工具编译,也可以用arthas提供mc(Memory Compiler/内存编译器)工具编译
如上,编译得到MathGame.class字节码文件,下面则是通过arthas的redefine命令发布到JVM中
发布前,我们再次确认,当前MathGame运行的结果是
没有执行我们加入的代码System.out.println("动态加的代码,打印number值为:" + number)
执行redefine /Users/creasylai/program/arthas-bin/demo/MathGame.class
再观察MathGame运行的结果
这时候,我们加入的代码就已经执行了。
其他:
其实arthas提供了watch命令,可以直接观察方法执行的入参、返回值等,在上方的场景,我们没必要加打印语句了
执行命令
watch demo.MathGame primeFactors "{params,returnObj}" -x 2"
如上图,入参和返回值都打印出来了(返回值为null是因为p rimeFactors方法抛出异常了)
- arthas还有很多有用的命令,如trace可以追踪每个函数的执行耗时,dashboard可以查看程序的运行状态等
下方链接为arthas在线教程
基础教程【十分钟】https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn&id=arthas-basics
进阶教程【十分钟】https://arthas.aliyun.com/doc/arthas-tutorials.html?language=cn&id=arthas-advanced