JVMNotes

第 24 章:Arthas

zjc 于 2026-01-24 发布

这是《JVM 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Arthas 是阿里开源的 Java 在线诊断工具。它允许 attach 到运行中的 JVM,查看线程、内存、类加载、方法调用、参数返回值和耗时,适合在测试或受控生产环境中定位疑难问题。

使用在线诊断工具要遵守权限和变更流程:它可能读取敏感数据,增强类也会带来少量开销。

24.1 安装与启动

下载并启动:

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

启动后会列出 Java 进程,输入编号 attach。

也可以直接指定 pid:

java -jar arthas-boot.jar <pid>

退出并释放增强:

stop

如果只执行 exit,本地会话退出,但服务端可能仍在。生产用完应执行 stop

24.2 基础命令

命令 用途
dashboard 总览
thread 线程列表和栈
jvm JVM 信息
sysprop 系统属性
sysenv 环境变量
sc 查看已加载类
sm 查看方法
jad 反编译类
getstatic 读取静态字段
heapdump 导出堆
logger 查看和修改日志级别

示例:

dashboard
thread -n 5
thread -b
jvm
sc -d com.demo.OrderService

thread -b 用于找出阻塞其他线程最多的锁持有线程。

24.3 watch 方法

watch 可以观察方法入参、返回值和异常。

基础形式:

watch com.demo.OrderService create params returnObj throwExp -x 2

常见参数:

参数 含义
params 方法参数
returnObj 返回值
throwExp 抛出的异常
target 当前对象
-x 展开层级
-n 匹配次数

条件过滤:

watch com.demo.OrderService create params returnObj 'params[0] > 1000' -x 2 -n 3

这表示只观察第一个参数大于 1000 的调用,最多 3 次。

注意:打印过大的对象可能拖慢请求,也可能刷爆终端。生产上要加条件和次数。

24.4 trace 耗时

trace 用于查看调用链中每层方法的耗时。

trace com.demo.OrderService create -n 5 --skipJDKMethod false

输出中可以看到每个子调用的耗时占比。适合回答:一个接口慢,到底慢在 SQL、RPC、序列化还是自身计算。

常用技巧:

# 只看超过 100ms 的调用
trace com.demo.OrderService create '#cost > 100' -n 5

限制:

  1. 只能看到匹配类的方法链;
  2. 方法增强有开销;
  3. 异步和动态代理可能需要换切点;
  4. 线程切换会导致栈不连续;
  5. 极高频方法要严格限制次数。

24.5 stack 查看调用来源

stack 输出方法被调用时的调用栈:

stack com.demo.OrderService create -n 5

适合定位:

  1. 某个方法被谁调用;
  2. 意外路径从哪里进入;
  3. 缓存穿透来源;
  4. 定时任务触发链。

如果调用非常频繁,同样要加过滤条件。

24.6 tt 时间隧道

tt 可以记录方法调用,之后回看参数、返回值和调用栈。

tt -t com.demo.OrderService create -n 10
tt -l
tt -i 1000
tt -i 1000 -p

含义:

命令 用途
-t 记录调用
-l 列出记录
-i 查看指定编号
-p 重放调用

重放请求可能再次写数据库或调用下游,生产环境必须确认幂等和安全。

24.7 热更新能力

Arthas 支持 retransform 加载修改后的 class,但热更新不适合作为常规发布方式。

风险:

  1. 只替换方法体,不能随意改变类结构;
  2. 与下一次正式发布可能不一致;
  3. 造成“线上行为和代码仓库不一致”;
  4. 增强残留可能影响性能;
  5. 审计和回滚困难。

更稳妥的用法是:热更新只作为极端应急手段,操作前保存证据,操作后尽快正式发布等价代码。

24.8 排查 CPU 高

步骤:

1. dashboard 观察 CPU 和线程
2. thread -n 5 找高 CPU 线程
3. 查看线程栈
4. trace 或 profiler 定位热点方法
5. jad 查看线上类是否与预期一致
6. 结合日志和监控确认

示例:

dashboard
thread -n 5
thread <thread-id>
trace com.demo.TaskService execute '#cost > 100' -n 5

如果高 CPU 是 GC 线程,应转向 GC 日志和堆分析,而不是业务方法。

24.9 排查接口偶发慢

建议流程:

1. 确认入口类和方法
2. trace 加成本过滤
3. watch 保存异常请求参数
4. 检查 SQL、RPC、锁、线程池
5. 对比正常和异常调用
6. 用业务日志补充时间线

示例:

trace com.demo.OrderController detail '#cost > 200' -n 10
watch com.demo.OrderController detail params returnObj throwExp -x 2 -n 10
thread --state BLOCKED

偶发问题要先拿到样本,再缩小范围。

24.10 安全与治理

生产使用建议:

  1. 通过跳板机或运维平台执行;
  2. 记录操作审计;
  3. 敏感字段脱敏;
  4. 限制 -n 和条件;
  5. 用完执行 stop
  6. 不长期保留方法增强;
  7. 灰度实例操作;
  8. 避免在无降级能力的核心链路随意 watch 大对象。

本章小结

Arthas 能在不重启 JVM 的情况下观察线程、方法、参数、返回值、调用链和类加载信息,是定位线上疑难问题的利器。watchtracestacktt 是核心命令,但都应加条件、次数和时长限制。生产使用要重视权限、审计、敏感数据和释放增强。

思考题

  1. watch 和日志埋点各有什么优劣?
  2. 为什么 trace 需要加 #cost 条件?
  3. thread -b 能解决什么问题?
  4. tt -p 在生产中有什么风险?
  5. 使用 Arthas 后为什么要执行 stop