第 77 章:Arthas 与线上诊断
学习目标
- 掌握 Arthas 常用命令排查线上问题
- 学会热更新代码、监控方法耗时、查看调用栈
- 理解 JVM 调优基础
一、为什么需要 Arthas?
场景:
- 线上接口突然慢了,怎么定位是哪个方法慢?
- 怀疑某个方法有 bug,但日志没打,怎么在线查看参数?
- 紧急 bug 需要修复,但发布要半小时,能不能热更新?
- JVM 内存高,怎么看是谁占用了?
Arthas(阿尔萨斯)是阿里开源的 Java 诊断工具,无需重启 JVM,在线诊断。
bash
# 安装(Linux/Mac)
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
# Windows
java -jar arthas-boot.jar启动后选择要诊断的 Java 进程,进入交互式命令行。
二、dashboard:全局看板
bash
dashboard关键指标:
- Heap 内存:used / total / max
- GC 次数:年轻代 / 老年代
- 线程数:RUNNABLE / TIMED_WAITING / BLOCKED
- 系统:CPU 负载、内存使用率
三、thread:线程分析
查最忙的线程
bash
thread -n 3 # CPU 占用最高的 3 个线程输出:
ID NAME STATE %CPU
22 http-nio-8080-exec-5 RUNNABLE 8.3%
25 http-nio-8080-exec-8 RUNNABLE 5.1%
31 scheduling-1 TIMED_WAIT 0.2%看线程栈
bash
thread 22 # 查看 22 号线程的栈
thread -b # 查看 BLOCKED 的线程(找死锁)
thread -w {threadId} # 等待指定线程结束java
// 输出示例:
"http-nio-8080-exec-5" #22 daemon prio=5 tid=0x00007f...
java.lang.Thread.State: RUNNABLE
at com.taskflow.service.OrderService.queryOrder(OrderService.java:42)
at com.taskflow.controller.OrderController.list(OrderController.java:30)
...实战:监控到 BLOCKED 线程数突然飙升 → 怀疑死锁或锁竞争。
四、watch:观察方法调用
bash
# 监控 OrderService.createOrder 方法的入参和返回值
watch com.taskflow.service.OrderServiceImpl createOrder \
"{params, returnObj, throwExp, cost}" \
-x 5| 参数 | 含义 |
|---|---|
params | 入参(数组) |
returnObj | 返回值 |
throwExp | 异常 |
cost | 耗时(ms) |
-x | 展开对象层级 |
实战:监控慢方法
bash
# 监控所有调用,耗时超过 200ms 的
watch com.taskflow.service.OrderService * \
"{params, returnObj, throwExp, cost}" \
'#cost > 200' \
-x 5实战:监控特定参数
bash
# 只监控 userId=1001 的调用
watch com.taskflow.service.UserService getById \
"{params[0], returnObj}" \
'params[0] == 1001'五、trace:方法调用路径
bash
# 追踪 queryOrder 方法的完整调用链
trace com.taskflow.service.OrderService queryOrder \
'#cost > 100' \
-n 5输出:
`---ts=2026-08-12 14:23:45;thread_name=http-nio-exec-3;id=23;is_daemon=true;priority=5;TCCL=...
`---[245.231ms] com.taskflow.service.OrderService:queryOrder()
+---[180.123ms] com.taskflow.mapper.OrderMapper:selectList()
| `---[175.012ms] org.mybatis:selectList()
+---[ 35.220ms] com.taskflow.service.UserService:getById()
| `---[ 30.112ms] com.taskflow.mapper.UserMapper:selectById()
`---[ 25.432ms] com.taskflow.service.InventoryService:checkStock()一眼看出:selectList 用了 180ms,是性能瓶颈。
trace vs monitor:
trace看完整调用链(深度)monitor看方法统计(广度)
六、monitor:方法统计
bash
# 每 5 秒统计一次方法调用情况
monitor com.taskflow.service.OrderService createOrder -c 5输出:
timestamp class method total success fail avg-rt(ms) fail-rate
2026-08-12 14:25:00 com.taskflow.service.OrderService createOrder 1234 1230 4 12.34 0.32%
2026-08-12 14:25:05 com.taskflow.service.OrderService createOrder 1189 1189 0 11.23 0.00%关键指标:
avg-rt:平均响应时间fail-rate:失败率total:调用次数
七、jad:反编译
bash
# 查看线上跑的类源码
jad com.taskflow.service.OrderServiceImplbash
# 反编译特定方法
jad com.taskflow.service.OrderServiceImpl createOrder实战:怀疑线上跑的代码和 Git 不一致(发布出错了)→ 用 jad 反编译确认。
八、sc / sm:查类和方法
bash
# 查加载的类
sc com.taskflow.* | head -20
# 查类的方法
sm com.taskflow.service.OrderServiceImpl输出:
com.taskflow.service.OrderServiceImpl
createOrder(OrderDTO)
updateOrder(OrderDTO)
queryOrder(Long)
deleteOrder(Long)九、ognl:执行表达式
bash
# 调用静态方法
ognl '@java.lang.System@getProperty("user.dir")'
# 查 Spring Bean 的属性
ognl '@com.taskflow.context.SpringContextHolder@getBean("orderServiceImpl").status'
# 查线程数
ognl '@java.lang.management.ManagementFactory@getThreadMXBean().getThreadCount()'十、profiler:火焰图
bash
# 启动采样
profiler start -e cpu
# 30 秒后停止,生成火焰图
profiler stop --format html火焰图横轴是 CPU 时间占比,纵轴是调用栈。一眼看出哪个方法占用了最多 CPU。
十一、dashboard 与日志
bash
# 查日志(Arthas 内置 logger)
logger
logger --name ROOT --level debug
# 查运行参数
sysprop
sysenv十二、热更新代码(高级)
风险高,生产慎用!仅用于紧急 bug 修复。
bash
# ① 下载源码
jad --source-only com.taskflow.service.OrderServiceImpl > /tmp/OrderServiceImpl.java
# ② 编译修改后的类
mc /tmp/OrderServiceImpl.java -d /tmp/output
# ③ 加载新类(热更新)
retransform /tmp/output/com/taskflow/service/OrderServiceImpl.class实际生产中一般用 Arthas 的
redefine命令(更稳定)。
十三、JVM 调优基础
内存参数
bash
java -Xms2g -Xmx2g -Xmn1g -XX:MaxMetaspaceSize=512m -jar app.jar| 参数 | 说明 |
|---|---|
-Xms | 初始堆大小 |
-Xmx | 最大堆大小 |
-Xmn | 年轻代大小 |
-XX:MaxMetaspaceSize | 元空间上限 |
GC 日志
bash
java -Xlog:gc*:file=/var/log/gc.log:time,uptime,level,tags -jar app.jarbash
# 实时 GC 监控
jstat -gc <pid> 1000 # 每秒打印 GC 情况内存分析
bash
# 导出堆 dump
jmap -dump:format=b,file=heap.bin <pid>
# 用 MAT 分析
# 1. Histogram:查最大对象
# 2. Leak Suspects:自动检测内存泄漏
# 3. Dominator Tree:查引用链十四、线上问题排查流程
十五、Arthas 最佳实践
bash
# ① 监控脚本(批处理)
# 把常用命令写到文件
echo "dashboard" > /tmp/arthas.cmd
echo "thread -n 3" >> /tmp/arthas.cmd
echo "monitor com.taskflow.* * -c 5" >> /tmp/arthas.cmd
# 执行
java -jar arthas-boot.jar -f /tmp/arthas.cmd
# ② 远程连接
java -jar arthas-boot.jar --target-ip <ip> --port <port>
# 然后用 telnet / Web Console 远程连接| 场景 | 推荐命令 |
|---|---|
| 看全局状态 | dashboard |
| 查 CPU 高 | thread -n 5 |
| 查慢方法 | trace + 条件过滤 |
| 查异常 | watch + throwExp |
| 查调用统计 | monitor |
| 查类是否更新 | jad |
| 内存问题 | dashboard + jmap 导堆 |
十六、生产安全
bash
# ① 只允许特定用户使用 Arthas
# 配置项:arthas.enableArthas=false 关闭
# 通过环境变量控制:ARTHAS_ENABLE=false
# ② Arthas Web Console 用 HTTPS
# 默认是 HTTP,生产应配置反向代理
# ③ 监控 Arthas 自身
# Arthas 会占用一点 CPU/内存,需要监控十七、本章小结
| 要点 | 关键 |
|---|---|
| 启动 | java -jar arthas-boot.jar |
| 全局 | dashboard |
| 线程 | thread -n 3、thread -b |
| 监控 | watch(参数/异常)、trace(调用链)、monitor(统计) |
| 反编译 | jad |
| 表达式 | ognl '@Class@method()' |
| 热更新 | jad + mc + retransform(慎用) |
| JVM | jmap(堆)、jstat(GC)、jstack(线程) |
| 流程 | dashboard → thread → trace → watch |
动手练习
练习 1:基础题
在本地启动一个 Spring Boot 应用,连接 Arthas。执行:
dashboard看全局thread -n 3找最忙线程watch一个自定义方法,打印入参和返回值
练习 2:进阶题
模拟一个慢方法:
java
public void slowMethod() {
Thread.sleep(500);
System.out.println("done");
}用 trace 命令追踪到具体的耗时环节。
练习 3:思考题
线上一个接口突然变慢(从 50ms 变成 2s),如何用 Arthas 快速定位根因?写出完整的排查步骤。
下一章:第 78 章:Docker 镜像构建 →