Arthas 阿尔萨斯
18 个章节
Java 应用在线诊断工具 Arthas 的背景、核心概念和常用命令记录。
Arthas 阿尔萨斯
1. 背景与目标
技术背景
Arthas是阿里巴巴开源的一款Java诊断工具,旨在解决生产环境中Java应用的问题排查难题。在传统的Java应用运维中,当遇到CPU飙升、内存溢出、线程阻塞等问题时,开发者通常需要使用jps、jstack、jmap、jhat等JDK自带工具进行诊断,过程繁琐且效率低下。
Arthas的出现彻底改变了这一现状,它提供了一个统一的命令行界面,集成了大部分JDK诊断工具的功能,能够在不修改代码、不重启服务的情况下,实时监控和诊断运行中的Java应用。
解决的问题和应用场景
- 类加载问题诊断:快速定位类从哪个jar包加载,解决ClassNotFoundException和NoClassDefFoundError
- 代码执行问题:确认修改的代码是否被执行,避免因分支错误或未提交导致的问题
- 性能瓶颈分析:定位方法执行耗时长的原因,生成火焰图分析热点
- 线上调试困难:无需加日志重新发布,直接在线调试生产环境
- 死锁和线程阻塞:快速发现和定位线程死锁、阻塞问题
- 内存泄漏检测:监控JVM内存使用情况,发现内存泄漏点
- 动态代码修改:无需重启服务,热更新类文件修复紧急问题
2. 核心概念和底层原理
核心概念
- Attach机制:Arthas通过VirtualMachine.attach()方法将自身注入到目标Java进程中
- 字节码增强:利用ASM等字节码操作库,在运行时动态修改类的字节码以插入监控逻辑
- 类隔离:使用自定义ClassLoader防止Arthas的类与业务类冲突
- 命令系统:提供丰富的命令集合,覆盖各种诊断场景
底层原理
Arthas的工作原理可以分为以下几个步骤:
- 进程连接:通过Java VirtualMachine API连接到目标Java进程
- Agent注入:将Arthas的Agent模块注入到目标JVM中
- 字节码织入:使用ASM等工具在目标类的方法中织入监控代码
- 命令执行:用户通过命令行发送指令,Arthas解析并执行相应操作
- 结果返回:将诊断结果以友好的方式展示给用户
// 简化的Arthas工作流程示意图
// 1. 用户启动Arthas并选择目标进程
// 2. Arthas通过Attach API连接目标JVM
// 3. 注入Agent到目标JVM
// 4. 用户执行诊断命令(如trace)
// 5. Arthas使用ASM修改目标类字节码,插入监控逻辑
// 6. 目标方法执行时收集监控数据
// 7. 将结果返回给用户界面
技术优势
- 无侵入性:无需修改应用代码,不重启服务
- 实时性:在线诊断,实时反馈结果
- 全面性:覆盖性能分析、问题定位、动态修改等多个维度
- 易用性:命令行交互,丰富的Tab自动补全
3. 常用命令和使用方法
安装和启动
# 下载arthas-boot.jar
curl -O https://arthas.aliyun.com/arthas-boot.jar
# 启动Arthas
java -jar arthas-boot.jar
# 使用阿里云镜像加速下载(可选)
java -jar arthas-boot.jar --repo-mirror aliyun --use-http
基础命令
# 查看帮助信息
help
# 查看Arthas版本
version
# 查看当前会话信息
session
# 清屏
cls
# 查看命令历史
history
# 退出当前连接(Arthas仍在运行)
quit
# 停止Arthas服务
stop
JVM相关信息命令
# 查看JVM实时运行状态
dashboard
# 查看JVM信息
jvm
# 查看JVM系统属性
sysprop
# 查看环境变量
sysenv
# 查看JVM选项
vmoption
# 查看类的静态属性
getstatic
# 查看内存信息
memory
# 查看MBean信息
mbean
# 查看Perf Counter信息
perfcounter
# 执行GC
vmtool --action forceGc
类和类加载器相关命令
# 查看已加载的类信息
sc -d com.example.*
# 查看类的方法信息
sm com.example.MyClass
# 反编译已加载类的源码
jad com.example.MyClass
# 查看类加载器继承树
classloader
# dump已加载类的bytecode
dump com.example.MyClass
# 内存编译.java文件为.class文件
mc /tmp/MyClass.java
# 加载外部的.class文件到JVM中(redefine)
redefine /tmp/MyClass.class
# 加载外部的.class文件到JVM中(retransform)
retransform /tmp/MyClass.class
监控和跟踪命令
# 方法执行监控
monitor -c 5 com.example.MyClass myMethod
# 输出方法被调用的调用路径
stack com.example.MyClass myMethod
# 方法内部调用路径,并输出方法路径上的每个节点上耗时
trace com.example.MyClass myMethod
# 跟踪方法执行路径并过滤耗时超过100ms的调用
trace com.example.MyClass myMethod '#cost > 100'
# 方法执行数据观测
watch com.example.MyClass myMethod '{params, returnObj}' -x 2
# 记录方法执行数据的时空隧道
tt -t com.example.MyClass myMethod
线程相关命令
# 查看线程信息,支持多种参数
thread
# 查看阻塞线程
thread -b
# 查看指定线程ID的信息
thread 1
# 查看Top N线程
thread -n 5
thread -n 3 #打印最忙的3个线程堆栈信息
thread -i 1000 # 统计最近1000ms内的线程CPU时间
thread -n 3 -i 1000 # 列出1000ms内最忙的3个线程栈
Profiler和火焰图
# 使用async-profiler进行采样
profiler start
# 停止采样并生成火焰图
profiler stop --format html
# 查看采样状态
profiler status
快速开始
-
先下载一个demojar包
wget https://arthas.aliyun.com.math-game.jar, 并启动java -jar math-game.jar -
下载arthas
curl -O https://arthas.aliyun.com/arthas-boot.jar另外窗口启动java -jar arthas-boot.jar -
启动之后显示当前正在运行的java进程

-
输入2 , 显示该进程信息, 此时已经进入了arthas的 bash模式

-
使用arthas键入命令即可, 退出bash 使用
exit或quit, 完全停止arthas使用stop
dashboard
当前系统的实时数据面板,按 ctrl+c 退出

数据说明
- ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应。
- NAME: 线程名
- GROUP: 线程组名
- PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
- STATE: 线程的状态
- CPU%: 线程的cpu使用率。比如采样间隔1000ms,某个线程的增量cpu时间为100ms,则cpu使用率=100/1000=10%
- DELTA_TIME: 上次采样之后线程运行增量CPU时间,数据格式为
秒 - TIME: 线程运行总CPU时间,数据格式为
分:秒 - INTERRUPTED: 线程当前的中断位状态
- DAEMON: 是否是daemon线程
JVM内部线程
Java 8之后支持获取JVM内部线程CPU时间,这些线程只有名称和CPU时间,没有ID及状态等信息(显示ID为-1)。 通过内部线程可以观测到JVM活动,如GC、JIT编译等占用CPU情况,方便了解JVM整体运行状况。
- 当JVM 堆(heap)/元数据(metaspace)空间不足或OOM时,可以看到GC线程的CPU占用率明显高于其他的线程。
- 当执行
trace/watch/tt/redefine等命令后,可以看到JIT线程活动变得更频繁。因为JVM热更新class字节码时清除了此class相关的JIT编译结果,需要重新编译。
JVM内部线程包括下面几种:
- JIT编译线程: 如
C1 CompilerThread0,C2 CompilerThread0 - GC线程: 如
GC Thread0,G1 Young RemSet Sampling - 其它内部线程: 如
VM Periodic Task Thread,VM Thread,Service Thread