调试排错 - Arthas使用
Arthas简介
Arthas是什么
Arthas 是 Alibaba 开源的 Java 诊断工具。支持 JDK6+, 采用命令行交互模式,提供 Tab 自动补全,可以方便定位和诊断线上程序的运行问题。
Arthas入门
Arthas安装
下载 arthas-boot.jar,然后用 java -jar 的方式启动:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
2
Arthas能解决什么问题
使用 Arthas 可以帮助你解决:
- 可以很方便查到一类是从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
 - 怀疑自己的代码未被部署到服务器,可以通过命令快速验证服务器上的代码就是本地的代码;
 - 可以直接通过 arthas 进行线上 debug,查看方法返回值以确认问题所在;
 - 可以很方便嵌入自己的 debug 代码,快速验证猜想;
 - 操作完成后,可以将所有 debug 代码删除,从而避免影响线上运行;
 
常用命令
dashboard
dashboardopen in new window 命令可以查看当前系统的实时数据面板。

面板中 Thread 各数据说明:
| 名称 | 说明 | 
|---|---|
| ID | Java级别的线程ID,注意这个ID不能跟 jstack 中的 nativeID 一一对应 | 
| NAME | 线程名 | 
| GROUP | 线程组名 | 
| PRIORITY | 线程优先级, 1~10之间的数字,越大表示优先级越高 | 
| STATE | 线程的状态 | 
| CPU% | 线程的cpu使用率。比如采样间隔1000ms,某个线程的增量cpu时间为100ms,则cpu使用率=100/1000=10% | 
| DELTA_TIME | 上次采样之后线程运行增量CPU时间,数据格式为秒 | 
| TIME | 线程运行总CPU时间,数据格式为分:秒 | 
| INTERRUPTED | 线程当前的中断位状态 | 
| DAEMON | 是否是daemon线程 | 
JVM内部线程包括下面几种:
- JIT编译线程: 如 C1 CompilerThread0、 C2 CompilerThread0
 - GC线程: 如 GC Thread0、 G1 Young RemSet Sampling
 - 其它内部线程: 如 VM Periodic Task Thread,、VM Thread、 Service Thread
 
thread
threadopen in new window 命令可以查看当前 JVM 的线程堆栈信息。一目了然的了解系统的状态,哪些线程比较占cpu,他们到底在做什么。
thread 参数列表:
| 参数名称 | 参数说明 | 
|---|---|
| id | 线程id | 
| -n | 指定最忙的前N个线程并打印堆栈 | 
| [b] | 找出当前阻塞其他线程的线程 | 
| [i ] | 指定cpu占比统计的采样间隔,单位为毫秒 | 
| [--all] | 显示所有匹配的线程 | 
例如:thread -n 3 展示当前最忙的前3个线程并打印堆栈
classloader
classloaderopen in new window 命令将 JVM 中所有的 classloader 的信息统计出来,并可以展示继承树,urls 等。了解当前系统中有多少类加载器,以及每个加载器加载的类数量,帮助您判断是否有类加载器泄露。
jad
jadopen in new window 命令可以对类进行反编译。将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于你理解业务逻辑。
参数列表:
| 参数名称 | 参数说明 | 
|---|---|
| class-pattern | 类名表达式匹配 | 
[c:] | 类所属 ClassLoader 的 hashcode | 
[classLoaderClass:] | 指定执行表达式的 ClassLoader 的 class name | 
| [E] | 开启正则表达式匹配,默认为通配符匹配 | 
例如:jad java.lang.String toString
monitor
monitoropen in new window 监控某个特殊方法的调用统计数据,包括总调用次数,平均 rt,成功率等信息,每隔5秒输出一次。
watch
watchopen in new window 命令用于方法执行数据观测。可以观察指定方法的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。
参数列表:
| 参数名称 | 参数说明 | 
|---|---|
| class-pattern | 类名表达式匹配 | 
| method-pattern | 方法名表达式匹配 | 
| express | 观察表达式,主要由 ognl 表达式组成,默认值:{params, target, returnObj} | 
| condition-express | 条件表达式 | 
| [b] | 在方法调用之前观察 | 
| [e] | 在方法异常之后观察 | 
| [s] | 在方法返回之后观察 | 
| [f] | 在方法结束之后(正常返回和异常返回)观察 | 
| [E] | 开启正则表达式匹配,默认为通配符匹配 | 
| [x:] | 指定输出结果的属性遍历深度,默认为 1 | 
例子:watch demo.MathGame primeFactors "{params,throwExp}" -e 观察方法 demo.MathGame#primeFactors 执行的入参,仅当方法抛出异常时才输出
tt
ttopen in new window 命令是 Time Tunnel 缩写,方法执行数据的时空隧道,可以录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测。
退出arthas
如果只是退出当前的连接,可以用 quit 或者 exit 命令。Attach 到目标进程上的 arthas 还会继续运行,端口会保持开放,下次连接时可以直接连接上。
如果想完全退出 arthas,可以执行 stop 命令。
更多命令
实际场景
查看最繁忙的线程,以及是否有阻塞情况发生?
thread -n 3 # 查看最繁忙的三个线程栈信息
thread  # 以直观的方式展现所有的线程情况
thread -b #找出当前阻塞其他线程的线程
2
3