问题
公司接了一个二次开发兼维护的Spring Cloud的项目,输出异常日志就打印了exception.msg(),没有输出 e.printStackTrace()
,比如抛出了一个NullPointException
,就输出了一个java.lang.NullPointerException
,具体哪一行报错,也没输出。因为是线上的代码,不像测试环境,可以随意更新代码。这时候 arthas
就上场了。
arthas 来源
Arthas
是Alibaba
开源的Java
诊断工具,深受开发者喜爱。Arthas
是一款开源在线 Java
诊断工具,采用命令行交互模式,支持 web
端在线诊断,同时提供丰富的 Tab
自动补全功能,进一步方便进行问题的定位和诊断。得益于 Arthas
强大且丰富的功能,让 Arthas
能做的事情超乎想象。
arthas 可以解决哪些问题
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
是否有一个全局视角来查看系统的运行状况?
有什么办法可以监控到JVM的实时运行状态?
怎么快速定位应用的热点,生成火焰图?
arthas 如何安装
下载 arthas-boot.jar
,然后用 java -jar
的方式启动:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
arthas 常用命令
dashboard
当前系统的实时数据面板,按 ctrl+c 退出。
当运行在Ali-tomcat时,会显示当前tomcat的实时信息,如HTTP请求的qps, rt, 错误数, 线程池信息等等。
thread
查看当前线程信息,查看线程的堆栈
支持一键展示当前最忙的前N个线程并打印堆栈:
$ thread -n 3
thread -b, 找出当前阻塞其他线程的线程
$ thread -b
注意, 目前只支持找出synchronized关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持。
watch
让你能方便的观察到指定方法的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。
watch 的参数比较多,主要是因为它能在 4 个不同的场景观察对象
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
express | 观察表达式 |
condition-express | 条件表达式 |
[b] | 在方法调用之前观察 |
[e] | 在方法异常之后观察 |
[s] | 在方法返回之后观察 |
[f] | 在方法结束之后(正常返回和异常返回)观察 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[x:] | 指定输出结果的属性遍历深度,默认为 1 |
观察方法出参和返回值
$ $ watch com.slf.arthas.controller.DemoController login '{params,returnObj,throwExp}' -n 5 -x 3
观察异常信息的例子
$ watch demo.MathGame primeFactors "{params[0],throwExp}" -e -x 2
jad
反编译指定已加载类的源码
jad 命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于你理解业务逻辑;
- 在 Arthas Console 上,反编译出来的源码是带语法高亮的,阅读更方便
- 当然,反编译出来的 java 代码可能会存在语法错误,但不影响你进行阅读理解
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
[c:] | 类所属 ClassLoader 的 hashcode |
[classLoaderClass:] | 指定执行表达式的 ClassLoader 的 class name |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
编译java.lang.String
jad java.lang.String
反编译指定的函数
jad demo.MathGame main
arthas 在线教程:arthas.aliyun.com/doc/arthas-…
左边是教程,右边可以输入命令
手把手教你,赶紧试试看吧。
遇到的问题
找不到 pid,未安装 jps
原因:centos 安装的是 open-jdk ,没有安装 jps 命令
解决方法: 需要安装java-1.X.X-openjdk-devel这个包,他提供了 jps 这个工具。
查询
yum list | grep jdk-devel
安装
yum install java-1.8.0-openjdk-devel.x86_64