线上出问题的时候,最难受的是「代码就在眼前,却看不到运行时」。重启加日志要等下一轮发布,慢方法定位靠猜,堆栈抓了看不懂。Arthas(阿里开源的 Java 诊断工具)让你无需重启、不改代码就能查看运行中的类、方法调用参数、返回值和异常栈,甚至热更新代码。本文从安装讲到命令实战与生产安全。
一、Arthas 是什么:线上诊断瑞士军刀
Arthas 通过 attach 到目标 JVM 进程,基于 Java Instrumentation 和字节码增强,在不改源码、不重启的前提下实现运行时观测与操作。
| 能力 | 说明 |
|---|---|
| 在线观测 | 看方法入参、返回值、异常、耗时 |
| 反编译 | jad 查看运行时真实字节码对应的源码 |
| 热更新 | redefine 用新编译的类替换运行中的类 |
| 线程分析 | thread 查看线程状态与阻塞原因 |
| 类加载 | classloader 查看类加载器与冲突 |
| OGNL | 直接读取/修改运行时对象属性 |
Arthas 适用场景:
生产环境偶发问题,日志不够用
排查慢接口、死锁、内存异常
临时热修复(有风险,需走流程)
排查类冲突、依赖版本问题
一句话总结: Arthas 是「运行中的显微镜 + 手术刀」——不重启、不改代码就能看方法调用、反编译类、热更新代码,是线上排障的第一梯队工具。
二、安装与启动
2.1 快速开始
# 下载 arthas-boot,或用包管理工具
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
# 交互选择要 attach 的 Java 进程,或直接指定 PID
java -jar arthas-boot.jar <pid>
# 也可以作为服务启动,支持远程连接
java -jar arthas-as-service.jar
2.2 基本交互
进入 Arthas 交互界面后:
help 查看所有命令
quit 退出(不影响目标进程)
session 查看当前会话信息
reset 重置所有增强过的类(恢复原始字节码)
shutdown 关闭 Arthas 服务端
# 非交互方式:attach 后执行单条命令即退出
java -jar arthas-boot.jar --attach-only <pid>
# 或通过 telnet/HTTP 接口脚本化调用
一句话总结: Arthas 用
java -jar arthas-boot.jar <pid>即可 attach;掌握reset、quit、shutdown三个命令是生产环境「全身而退」的前提。
三、常用命令速查
3.1 dashboard 与 thread
# 仪表盘:实时显示 CPU、内存、GC、线程概览
dashboard
# 查看所有线程及状态
thread
# 找出 CPU 占用最高的线程(Top 20)
thread -n 20
# 查看某个线程的完整堆栈
thread <threadId>
# 查看线程是否阻塞、等什么锁
thread -b
thread -b 输出解读:
如果有输出 → 找到了持锁线程,是死锁/锁等待的元凶
输出为空 → 没有线程在阻塞,问题可能是 IO 或 CPU 忙
3.2 watch 与 trace
# watch:观测方法调用的入参、返回、异常
watch com.example.OrderService placeOrder '{params, returnObj, throwExp}' -x 3
# trace:跟踪方法内部每一层的耗时
trace com.example.OrderService placeOrder
# 带条件观测:只有耗时超过 200ms 才打印
watch com.example.OrderService placeOrder '{params[0].userId}' '#cost > 200'
| 参数 | 含义 |
|---|---|
-n | 观测次数上限 |
-x | 展开对象深度 |
#cost | 本次调用耗时(ms) |
-e | 只观测异常 |
-f | 是否观测方法执行结束 |
一句话总结: 核心三板斧——
dashboard看全局、thread查线程、watch/trace钻方法;thread -b找持锁线程、#cost过滤慢调用是最常用的两个组合。
四、jad 反编译与 redefine 热更新
4.1 jad 反编译运行时类
# 查看线上真实运行的类源码(含行号)
jad com.example.OrderServiceImpl
# 只反编译某个方法
jad --source-only com.example.OrderServiceImpl placeOrder
# 定位类是从哪个 jar 加载的
sc -d com.example.OrderServiceImpl
jad 的价值:
1. 确认线上跑的到底是哪个版本的代码
2. 看字节码增强后的真实逻辑(是否有代理/包装)
3. 排查反编译结果与源码不一致 → 版本漂移
4.2 mc 与 redefine 热更新
# 1. 本地编译新代码
mc /tmp/Fix.java -d /tmp/out
# 2. 用编译产物替换运行中的类
redefine -c <classloaderHash> /tmp/out/com/example/Fix.class
# 3. 验证增强
jad com.example.Fix
// 一个临时修复的例子:原代码返回空导致 NPE
public class Fix {
public static String getConfig(String key) {
return "default_value"; // 临时兜底值
}
}
一句话总结:
jad确认「线上到底跑的什么代码」,mc + redefine提供临时热修复能力;但热更新只改变内存中的类,重启即失效,必须同时排期正式发布。
五、线程与内存排查
5.1 线程问题排查
# 高 CPU 定位:先找最耗 CPU 的线程,再看它的栈
thread -n 10
# 死锁检测
thread -b
# 锁竞争观察:配合 watch 看锁等待耗时
watch java.util.concurrent.locks.ReentrantLock lock '{params[0]}' -n 5
5.2 内存相关排查
# 查看堆使用概况
memory
# 查看 GC 情况
gc
# 查看类加载器及加载的类数量
classloader
# 查看某个类的实例数量与大小(需要开启)
# vmtool --action getInstances --className com.example.Cache --limit 100
Arthas 与堆转储的配合:
Arthas 适合快速看对象实例、类加载、GC 状态
大堆对象 / 引用链分析还是用 MAT 更全面
先用 Arthas 缩小范围,再 dump 给 MAT 深挖
一句话总结: 线程排查靠
thread -n、thread -b,内存排查靠memory、gc、vmtool看实例;Arthas 快速缩小范围,MAT 深挖引用链是高效的组合。
六、方法调用链与 OGNL
6.1 trace 定位慢方法
# 一层层展开,找到耗时子方法
trace -n 3 com.example.OrderService placeOrder '#cost > 100'
# 同时观测多个方法
trace com.example.OrderService placeOrder com.example.InventoryService checkStock
trace 输出解读:
每一行是一个子方法调用,右侧是耗时
看占比最大的子调用,就是慢的根源
继续对慢子方法再 trace,逐层下钻
6.2 OGNL 读取与修改变量
# 读取静态字段
ognl '@com.example.Config@INSTANCE.timeout'
# 调用方法
ognl '@java.lang.System@getProperty("user.dir")'
# 修改静态字段(谨慎!)
ognl -x 3 '@com.example.Config@INSTANCE.timeout = 5000'
OGNL 的边界:
能读:静态字段、对象属性、方法返回值
能改:静态字段、属性(慎用,影响所有线程)
不能:修改方法字节码、新增字段
一句话总结:
trace逐层下钻把「慢在哪一层」可视化;ognl直接操作运行时对象——读安全、改要慎,改静态配置时务必评估全局影响。
七、生产安全与权限
7.1 风险评估
| 操作 | 风险 | 管控建议 |
|---|---|---|
| watch/trace | 低,有性能开销 | 加 -n 限制次数,观测后 reset |
| jad/sc | 低,只读 | 无特殊限制 |
| ognl 修改 | 中,影响全局 | 只允许读,修改需审批 |
| redefine 热更新 | 高,改运行代码 | 必须走变更流程 + 留痕 + 回滚预案 |
| 日志敏感信息 | 中,可能泄露 | watch 表达式过滤敏感字段 |
7.2 安全规范
生产环境 Arthas 使用规范:
1. 仅在低峰期、白名单机器使用
2. 观测命令必须带 -n 限制,防止无限输出
3. 用完立即 reset / quit,不留增强字节码
4. 远程访问走安全通道(SSH 隧道 / HTTP 鉴权)
5. redefine 必须记录变更内容与时间,配套正式发布
# SSH 隧道远程访问 Arthas 的典型姿势
ssh -L 8563:localhost:8563 user@host
# 本地再通过 http://localhost:8563 访问 Arthas WebConsole
一句话总结: Arthas 功能越强大,越要约束使用边界——观测命令限量、修改操作审批、用完即 reset;权限与留痕是线上工具落地的前提。
八、实战陷阱清单
| 陷阱 | 现象 | 对策 |
|---|---|---|
| watch 无限输出 | 控制台刷屏、性能劣化 | 加 -n、#cost 条件 |
| 忘记 reset | 增强字节码残留 | 用完立即 reset |
| redefine 后重启失效 | 修复没生效 | 同时排期正式发布 |
| 类加载器冲突 | jad 找不到类 | 先 classloader 定位正确的 ClassLoader |
| OGNL 误改全局配置 | 全量行为变化 | 只读为主,修改需审批 |
| 高并发下 trace | 采集开销放大 | 低峰期使用,限制次数 |
| 敏感信息打印 | 日志泄露 | 过滤 params 表达式 |
九、总结
| 命令 | 用途 | 一句话 |
|---|---|---|
| dashboard | 全局状态 | 一眼看 CPU/GC/线程 |
| thread -b | 死锁定位 | 找出持锁元凶 |
| watch | 方法观测 | 看入参、返回、异常 |
| trace | 耗时下钻 | 慢在哪一层 |
| jad | 反编译 | 线上跑的什么代码 |
| redefine | 热更新 | 临时修复,重启失效 |
| ognl | 运行时操作 | 读安全,改要慎 |
一句话记住:Arthas 把「线上诊断」从「重启+加日志」升级为「即时观测+可控操作」。把它当手术刀而非常规工具:watch 限量、reset 及时、redefine 走流程,就能在关键时刻救急而不惹祸。
延伸阅读
- OOM 排查与堆转储分析 — Arthas 快速定位后,堆转储深挖引用链
- JFR 与 JMC 性能分析实战 — 常开低开销观测与 Arthas 互补
- JVM 内存与 GC 调优实战 — 线程与内存问题的底层机制
- Java 异常处理与防御式编程 — 线上异常与兜底设计的思路
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。