生产环境的 Spring Boot 应用一旦出现 CPU 飙高、接口响应变慢或者内存异常,最让人头疼的不是问题本身,而是排查手段太有限。看日志只能看到结果,看不到过程;本地复现又常常因为环境差异而失败;重启虽然能临时救急,但故障现场一消失,下一次出现又是从头再来。Arthas 的价值就在这里,它可以在不重启应用、不修改一行代码的前提下,直接 attach 到正在运行的 JVM 进程上,实时观察方法调用、参数返回值、线程状态和类加载情况,把排查粒度精确到某个方法的某一次调用。

Arthas 是怎么做到不停机诊断的
Arthas 的核心原理是 JVM 的 attach 机制。每个 Java 进程在启动时都会监听一个 attach 通道,外部进程可以通过这个通道向目标 JVM 发送指令,让它在运行时加载新的 Agent 包。Arthas 正是利用这一点,把自己的 Agent 注入到目标进程,然后通过字节码增强技术(Instrumentation API 加上 ASM 字节码操作)在指定的类和方法前后插入统计代码,从而实现方法级别的耗时监控、参数捕获和调用链追踪。
这种机制决定了 Arthas 的几个特点:第一,它是进程外的客户端加进程内的 Agent 架构,命令通过 telnet 或 HTTP 方式交互,退出时可以用 stop 命令彻底卸载增强,恢复字节码原状;第二,由于字节码会被修改,生产环境使用时要注意监控的方法不能是超高频调用的热点路径,否则增强本身会带来一定开销;第三,attach 需要与目标进程相同的用户权限,这一点在容器化部署时要特别注意。
安装接入与基础命令
接入方式非常简单,下载官方发布的 arthas-boot.jar,直接用 java 运行即可:
# 下载并启动 curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar # 启动后会列出所有 Java 进程,输入对应序号即可 attach # 也可以直接指定进程号 java -jar arthas-boot.jar 12345
attach 成功后先做几步基础检查。dashboard 命令可以一屏看到线程、内存、GC 次数和耗时,相当于一个实时更新的 jvisualvm 概览页;thread 命令列出所有线程的状态,thread -n 3 直接展示 CPU 占用最高的三个线程及其堆栈;sc -d com.example.OrderService 可以查看某个类是否被加载、从哪个 jar 包加载,用来确认依赖版本是否符合预期。
还有一个特别实用的命令是 jad,它能把运行中 JVM 里加载的类反编译成 Java 源码。线上排查时经常遇到“代码看起来是对的,但行为不对”的情况,多数时候是部署的包和本地代码不一致,用 jad 看一眼运行时真实的代码,能快速排除这类低级但高频的问题。
排查慢接口:trace 与 watch 的组合拳
假设某个下单接口偶尔超时,日志里没有明显异常,这时候可以先用 trace 命令定位耗时的分布。trace 会输出方法内部每一层子调用的耗时树,一眼就能看出时间花在了哪里:
# 追踪 Controller 方法的调用链,只打印耗时超过 100ms 的 trace com.example.controller.OrderController createOrder '#cost > 100'
trace 的输出是一个层级树,每一行显示一个内部调用的耗时和占比。如果发现耗时集中在 OrderService.queryStock,就可以继续对它 trace,一层层往下钻,最终通常会落在一次慢 SQL、一次远程调用的超时重试,或者一次锁竞争上。配合 #cost 条件过滤,可以只关注慢请求,避免正常请求刷屏。
定位到可疑方法后,再用 watch 观察它的入参、返回值和异常信息:
# 观察方法的入参、返回值和异常,条件是抛出异常时触发
watch com.example.service.OrderService queryStock '{params, returnObj, throwExp}' -e -x 2watch 支持 OGNL 表达式做条件过滤,比如只在返回值为 null 时触发、只在某个参数大于阈值时打印,这在排查“偶发脏数据”类问题时非常好用。需要注意 -x 参数控制对象展开层级,生产上不要设得太大,否则大对象的打印本身就会拖慢方法执行。
CPU 飙高与死锁的排查思路
CPU 飙高是最典型的线上故障。用 Arthas 排查的套路是固定的三步:先执行 thread -n 5 找出 CPU 最高的几个线程,命令输出会直接给出线程名和完整堆栈;如果堆栈显示业务代码在循环处理,多半是死循环或者正则回溯这类问题;如果堆栈停在 GC 线程上,那问题就不在业务线程而在内存,需要用 heapdump 命令导出堆快照做进一步分析。
# 查看 CPU 最高的线程 thread -n 5 # 检测死锁,如果存在会直接打印互相持有的锁 thread --blocked # 查看特定线程的详细堆栈 thread 42
死锁类问题用 thread --blocked 命令最直接,它会找出处于 BLOCKED 状态的线程并分析锁的持有关系。相比传统的 jstack 分析,Arthas 的输出已经做了解读,不需要自己去比对锁的 wait 和 hold 关系,排查效率高不少。
热更新验证与安全退出
Arthas 还提供一个进阶能力 retransform,可以在运行时替换已经加载的类。典型场景是线上确认了 bug 根因后,先热更新一个修复版类验证效果,确认有效再走正式的发版流程。使用流程是 jad 反编译源码,修改后用 mc 编译成字节码,最后 retransform 加载回去。但要强调,热更新只应作为应急验证手段,它不会改变磁盘上的 jar 包,应用重启后就会失效,而且频繁热更新容易造成类版本混乱。
排查结束后一定要执行 stop 命令而不是直接杀掉客户端。stop 会卸载所有字节码增强、恢复增强过的类并断开连接,直接退出可能留下增强代码继续运行,白白消耗性能。另外建议在生产环境按需使用,用完即停,不要让 Arthas 长期挂在核心服务上,这也是对线上稳定性最基本的敬畏。
ArthasSpring Boot生产环境诊断修改时间:2026-09-15 04:46:37