Arthas 实战与在线诊断
Arthas 是阿里巴巴开源的 Java 诊断工具,无需重启应用即可在线排查问题:方法调用参数/返回值、调用耗时、线程状态、内存占用、反编译类等。它是线上问题排查的利器。
安装与启动
方式一:下载 jar 启动
bash
curl -O https://github.com/alibaba/arthas/releases/download/arthas-all-3.7.2/arthas-bin.zip
unzip arthas-bin.zip
java -jar arthas-boot.jar方式二:快速安装脚本
bash
curl -L https://arthas.aliyun.com/install.sh | sh
./as.sh启动后选择目标 Java 进程即可进入交互式命令行。Windows 下可用 as.bat。
离线安装
生产环境无外网时,将 arthas 目录拷入目标机器,java -jar arthas-boot.jar 选择进程即可。
核心命令详解
watch — 观察方法调用
最常用的命令:查看方法的入参、返回值、异常。
watch com.example.service.OrderService createOrder '{params, returnObj}' -x 3| 参数 | 说明 |
|---|---|
| 类名+方法名 | 观察目标 |
| OGNL 表达式 | 定义输出内容:{params} 参数、returnObj 返回值、throwExp 异常 |
-x N | 展开对象的深度 |
-n N | 执行次数后停止 |
-b | 观察方法进入前(查看入参) |
-e | 只观察抛出异常时 |
bash
# 观察入参和返回值,展开 3 层
watch com.example.service.OrderService createOrder '{params, returnObj}' -x 3
# 只观察调用耗时超过 100ms 的调用
watch com.example.service.OrderService createOrder '{params[0], returnObj}' '#cost > 100'trace — 方法内部调用路径
观察方法内部各子方法的调用耗时,定位耗时瓶颈:
trace com.example.service.OrderService createOrder`---createOrder()
`---[50ms] orderMapper.selectById()
`---[30ms] redisTemplate.get()
`---[120ms] paymentService.pay()- 输出方法内部调用树 + 每步耗时
-n限制次数,--skipJDKMethod false是否包含 JDK 内部方法
monitor — 方法调用统计
按固定周期统计方法的调用次数、成功率、平均耗时:
monitor com.example.service.OrderService createOrder -c 5每 5 秒输出一次统计:调用次数、成功/失败次数、总耗时、平均耗时、成功率。
thread — 线程状态分析
查看线程信息,排查死锁、CPU 高占用、线程堆积:
thread # 所有线程概览(含 CPU 使用率)
thread -n 3 # 按 CPU 使用率排序前 3 的线程
thread -b # 查找阻塞其他线程的线程(死锁检测)
thread <tid> # 查看指定线程的堆栈bash
# 找到 CPU 占用最高的线程及其堆栈
thread -n 1thread -b 直接定位到阻塞源头,是死锁排查的快捷方式。
jad — 反编译
查看线上类实际加载的字节码(反编译为源码):
jad com.example.service.OrderService验证线上部署的代码版本是否正确、排查热部署后代码是否生效。
mc / redefine — 热更新
不重启应用,修改方法逻辑:
mc /tmp/OrderService.java -d /tmp # 内存编译
redefine /tmp/OrderService.class # 热更新类定义生产慎用,仅适合临时应急修复。
sc / sm — 类与方法查看
sc -d com.example.service.OrderService # 查看类加载器、class 位置
sm com.example.service.OrderService # 查看类的方法列表ognl — 表达式执行
直接执行 OGNL 表达式,读取静态字段、调用方法、查看 Spring Bean:
ognl '#root=@com.example.config.AppContext@getBean("orderService")' \
'#root.getStatus(1001)'常用场景:查看 Spring 容器 Bean 状态、修改运行期配置、调用内部方法验证逻辑。
实战案例
案例一:接口偶发超时定位
现象:接口偶尔 500ms+,无法用日志复现
排查:
1. trace 接口方法:发现 redisTemplate.get() 偶发 300ms+
2. 进一步 trace 到 jedis 内部:连接池获取等待
3. thread -n 3:部分线程 BLOCKED 在 JedisPool 上
结论:连接池默认 maxTotal 过小,高峰期连接耗尽
修复:调大连接池参数案例二:内存泄漏早期发现
现象:内存缓慢上涨,Full GC 频繁
排查:
1. monitor 关键缓存方法:写入量持续增长
2. watch 缓存 key:发现 key 无限增长,无过期
3. ognl 查看缓存 Map 大小确认增长
结论:缓存未设上限,改为带 TTL 的 Caffeine案例三:死锁快速定位
现象:服务卡死,请求全部超时
排查:
1. thread -b:直接输出"被阻塞线程"及"持有锁线程"
2. 两个线程互相等待对方持有的锁
结论:加锁顺序不一致导致死锁
修复:统一锁获取顺序命令速查表
| 命令 | 用途 | 高频参数 |
|---|---|---|
| watch | 观察入参/返回值/异常 | -x 展开深度、-n 次数、-e 异常 |
| trace | 方法内部耗时分布 | -n 次数 |
| monitor | 周期统计调用指标 | -c 周期秒数 |
| thread | 线程状态与死锁 | -n 数量、-b 阻塞定位 |
| jad | 反编译线上代码 | 无 |
| mc/redefine | 内存编译与热更新 | 无 |
| sc/sm | 类/方法信息 | -d 详细 |
| ognl | 表达式执行 | 无 |
| dashboard | 全局面板(CPU/内存/GC/线程) | 无 |
使用建议
- 只读命令优先:watch/trace/monitor/jad 无副作用,可放心使用
- 控制采样量:
-n限制次数,避免高并发下输出爆炸 - 热更新慎重:redefine 只应急,应尽快通过发布流程修复
- 配合其他工具:Arthas 适合"运行期动态观察",配合 jstat(GC 概览)、JFR(历史记录)形成完整排查链