1. Arthas工具概述与核心价值
第一次接触Arthas是在排查一个线上接口超时问题时,当时用jstack抓线程快照死活复现不了问题。同事扔过来一行curl -O https://arthas.aliyun.com/arthas-boot.jar命令,从此打开了JVM诊断的新世界。作为阿里开源的Java诊断利器,Arthas通过字节码增强技术实现了无需重启应用即可进行:
- 方法调用链路追踪(trace/watch)
- 实时方法入参/返回值监控(watch)
- 类加载信息统计(sc/sm)
- JVM运行时数据观测(dashboard)
- 热修复代码(redefine)
与JDK原生工具相比,最大的优势是无需预装任何Agent,直接通过attach机制动态注入诊断逻辑。下面这张对比表能清晰看出差异:
| 功能需求 | JDK工具 | Arthas |
|---|---|---|
| 查看加载类 | jmap -histo | sc -d className |
| 方法执行统计 | 需开发AOP代码 | monitor -c 5 mathGame |
| 实时观测方法参数 | 无法实现 | watch MathGame primeFactors |
| 线程堆栈分析 | jstack | thread -n 3 |
| 动态修改日志级别 | 需重启应用 | logger --name ROOT --level debug |
2. 环境准备与快速接入
2.1 安装方式选择
推荐三种安装方式,根据网络环境选择:
- 直接下载(生产环境首选):
bash复制wget https://arthas.aliyun.com/arthas-boot.jar
- 通过as.sh脚本安装(需要执行权限):
bash复制curl -L https://arthas.aliyun.com/install.sh | sh
- Docker方式(容器环境适用):
bash复制docker run --rm -it heyalex/arthas
注意:如果目标JVM运行在容器内,需要确保arthas与目标进程在同一PID命名空间,建议使用
docker exec进入容器后执行安装
2.2 启动与目标进程绑定
执行启动命令后会列出当前所有Java进程:
bash复制java -jar arthas-boot.jar
输出示例:
code复制[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 1234 com.example.Main
[2]: 5678 org.apache.catalina.startup.Bootstrap
输入对应序号后,Arthas会完成以下动作:
- 检查/tmp目录写入权限
- 下载必要的core/async模块
- 通过VirtualMachine.attach注入agent
常见问题处理:
- 如果遇到
attach permission denied,需要确认:- 当前用户与目标JVM进程属主一致
- 或者使用sudo提权执行
- 报错
java home not found时,显式指定JAVA_HOME:
bash复制JAVA_HOME=/usr/lib/jvm/java-11 java -jar arthas-boot.jar
3. 核心诊断场景实战
3.1 方法级观测(watch/trace)
观测方法返回值(适用于参数校验问题):
bash复制watch com.example.service.UserService getById "{params, returnObj}" -x 2
输出字段说明:
params:方法入参数组returnObj:方法返回对象-x 2:指定对象展开层级
追踪调用链路(排查性能问题时特别有用):
bash复制trace com.example.controller.* * -n 3 --skipJDKMethod false
关键参数:
-n 3:只显示耗时top3的路径--skipJDKMethod false:包含JDK内部方法调用
3.2 线程问题定位
快速定位CPU飙高问题:
bash复制thread -n 3 -i 1000
这个组合命令实现了:
- 每1000ms采样一次(-i参数)
- 显示CPU占用最高的3个线程(-n参数)
- 自动过滤等待状态的线程
死锁检测更简单:
bash复制thread -b
输出示例:
code复制Blocked thread commons-pool-EvictionTimer [TIMED_WAITING]
waiting to lock <0x0000000716f0b4a8>
which is held by Thread-5
3.3 热修复实战
紧急修复线上问题时的操作流程:
- 反编译当前类确认问题:
bash复制jad com.example.BugService
- 本地修改后编译成.class文件
- 上传到服务器执行热更新:
bash复制redefine /tmp/BugService.class
重要限制:不能修改方法签名/新增方法,只支持已有方法体的修改。建议先在同环境的测试实例验证
4. 高级技巧与性能优化
4.1 批量操作技巧
通过-c参数实现连续执行:
bash复制watch com.example.* * "{params,returnObj}" -x 2 -c 3
这个命令会对com.example包下所有类的所有方法进行观测,每3秒统计一次
管道组合命令示例:
bash复制thread | grep 'http-nio' | awk '{print $1}' | xargs thread
实现:筛选出包含"http-nio"的线程并查看详情
4.2 性能开销控制
通过以下方式降低诊断对生产系统的影响:
- 限制采样频率:
bash复制trace * * -n 5 --sampleInterval 50
- 使用轻量级命令:
bash复制profiler execute 'start,event=cpu,interval=1000000'
- 及时关闭不用的增强点:
bash复制reset
4.3 数据持久化
将会话记录保存到文件:
bash复制session -f /tmp/arthas.log
之后可以通过session -i /tmp/arthas.log回放
导出火焰图数据:
bash复制profiler start
profiler stop -f /tmp/flamegraph.html
5. 生产环境注意事项
-
权限控制:
- 禁止使用
ognl命令直接调用setter修改运行时数据 - 通过
--target-ip参数限制可访问IP
- 禁止使用
-
资源隔离:
bash复制
java -jar arthas-boot.jar --telnet-port 3658 --http-port 8563修改默认端口避免冲突
-
安全审计:
- 启用会话记录:
options save-result true - 定期检查
~/logs/arthas/目录下的操作日志
- 启用会话记录:
-
退出规范:
- 不要直接kill进程,正确做法:
bash复制
stop shutdown否则可能导致字节码残留
实际使用中发现,对于Spring Boot 2.3+的应用,建议添加JVM参数:
bash复制-Dspring.beaninfo.ignore=true
避免Arthas的类增强与Spring的bean初始化产生冲突