🔧 Arthas 详细教程

Java 应用诊断利器 - 阿里巴巴开源的 Java 诊断工具

🚀 什么是 Arthas?

Arthas 是阿里巴巴开源的 Java 诊断工具,当你遇到以下类似问题而束手无策时,Arthas 可以帮助你解决:

🔍 问题诊断

这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?

⚡ 性能分析

我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?

🎯 运行时修改

遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?

📊 实时监控

线上遇到某个用户的数据处理有问题,但线上同样的条件很难复现?

📥 安装方式

方式一:快速安装(推荐)

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

方式二:完整版下载

wget https://github.com/alibaba/arthas/releases/latest/download/arthas-packaging-latest-bin.zip unzip arthas-packaging-latest-bin.zip cd arthas ./as.sh

方式三:使用 as.sh

curl -L https://arthas.aliyun.com/install.sh | sh ./as.sh
💡 提示: 推荐使用第一种方式,arthas-boot.jar 会自动下载最新版本的 Arthas。

🎯 启动 Arthas

启动后,Arthas 会列出当前系统中的 Java 进程,选择需要诊断的进程即可。

$ java -jar arthas-boot.jar * [1]: 35542 [2]: 71560 arthas-demo.jar
📌 注意:
  • 选择进程编号,回车即可attach
  • 支持选择进程的PID,也支持只输入进程名进行模糊匹配
  • attach成功之后,会打印Arthas LOGO

📋 基础命令概览

命令 功能 示例
help 查看命令帮助信息 help watch
cls 清空当前屏幕区域 cls
session 查看当前会话的信息 session
reset 重置增强类 reset
version 输出当前目标Java进程所加载的Arthas版本号 version
history 打印命令历史 history
quit 退出当前Arthas客户端 quit
stop 关闭Arthas服务端 stop

🔍 JVM相关命令

dashboard - 实时数据面板

当前系统的实时数据面板,按 q 或者 Ctrl+C 退出。

dashboard dashboard -i 2000 -n 10
参数说明:
  • -i:刷新时间间隔,单位为毫秒
  • -n:刷新次数

thread - 查看当前JVM的线程堆栈信息

thread # 显示所有线程信息 thread 1 # 显示线程ID 1的栈 thread -n 3 # 显示最忙的前3个线程的栈 thread -b # 找出当前阻塞其他线程的线程 thread -i 10 -n 3 # 统计最近10秒内最忙的3个线程栈

jvm - 查看当前JVM信息

jvm

sysprop - 查看当前JVM的系统属性

sysprop # 查看所有属性 sysprop java.version # 查看指定属性 sysprop user.country CN # 修改属性值

sysenv - 查看JVM的环境属性

sysenv # 查看所有环境变量 sysenv USER # 查看指定环境变量

📦 class/classloader相关

sc - 查看JVM已加载的类信息

sc demo.* # 模糊搜索 sc -d demo.MathGame # 输出当前类的详情 sc -d -f demo.MathGame # 输出当前类的详情,包括这个类所加载的方法

sm - 查看已加载类的方法信息

sm java.lang.String # 查看类的方法 sm -d java.lang.String toString # 查看指定方法详情

jad - 反编译指定已加载类的源码

jad java.lang.String # 反编译String类 jad java.lang.String toString # 反编译String的toString方法

mc - 内存编译器

mc /tmp/Test.java # 编译.java文件为.class mc -c 327a647b /tmp/Test.java # 通过-c参数指定classloader

retransform - 加载外部的.class文件

retransform /tmp/Test.class # 加载指定的.class文件 retransform -c 327a647b /tmp/Test.class # 指定classloader

👀 监控命令详解

watch - 方法执行数据观测

能方便的观察到指定方法的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写OGNL表达式进行对应变量的查看。

# 观察方法出参和返回值 watch demo.MathGame primeFactors returnObj # 观察方法入参和出参 watch demo.MathGame primeFactors "{params,returnObj}" -x 2 # 观察方法执行前的参数 watch demo.MathGame primeFactors "{params}" -b # 观察异常信息 watch demo.MathGame primeFactors "{params,throwExp}" -e # 按照耗时进行过滤 watch demo.MathGame primeFactors '{params, returnObj}' '#cost>200' # 观察当前对象中的属性 watch demo.MathGame primeFactors 'target' # 使用通配符匹配多个方法 watch demo.MathGame * '{params, returnObj}' -x 2
参数说明:
  • -b:在方法调用之前观察
  • -e:在方法异常之后观察
  • -s:在方法返回之后观察,默认选项
  • -f:在方法结束之后(正常返回和异常返回)观察
  • -x:指定输出结果的属性遍历深度,默认为1

trace - 方法内部调用路径

trace命令能主动搜索 class-pattern/method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。

# 基本使用 trace demo.MathGame run # 根据调用耗时过滤 trace demo.MathGame run '#cost > 10' # 包含jdk的函数 trace --skipJDKMethod false demo.MathGame run # 过滤指定的类 trace -E com.test.ClassA|org.test.ClassB method1|method2

stack - 输出当前方法被调用的调用路径

# 基本使用 stack demo.MathGame primeFactors # 根据条件过滤 stack demo.MathGame primeFactors 'params[0]<0' -n 2 # 根据执行时间过滤 stack demo.MathGame primeFactors '#cost>5'

tt - 时间隧道

记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测。

# 开始记录 tt -t demo.MathGame primeFactors # 查看记录 tt -l # 查看指定记录的详细信息 tt -i 1003 # 重新执行指定的记录 tt -i 1004 -p # 搜索调用记录 tt -s 'method.name=="primeFactors"'
⚠️ 注意: tt命令有很多个主参数,这些主参数的意义是互斥的
  • -t:记录某个方法在一个时间段中的调用
  • -l:显示所有已经记录的列表
  • -n:只记录多少次
  • -s:搜索表达式
  • -i:查看指定记录的详细信息
  • -p:重新调用指定的记录

📊 monitor - 方法执行监控

对匹配 class-pattern/method-pattern的类、方法的调用进行监控。

# 基本监控,每5秒输出一次 monitor -c 5 demo.MathGame primeFactors # 指定监控的类和方法 monitor -c 5 demo.MathGame primeFactors run
监控项说明:
  • timestamp:时间戳
  • class:Java类
  • method:方法(构造方法、普通方法)
  • total:调用次数
  • success:成功次数
  • fail:失败次数
  • rt:平均RT
  • fail-rate:失败率

🔥 async-profiler

Arthas集成了async-profiler,可以用来生成火焰图来分析CPU性能热点。

🎯 profiler命令支持生成应用热点的火焰图。本质上是通过不断的采样,然后把收集到的采样结果生成火焰图。

基本使用

# 启动profiler,默认情况下,生成的是cpu的火焰图 profiler start # 获取已采集的sample的数量 profiler getSamples # 查看profiler状态 profiler status # 停止profiler,生成火焰图 profiler stop # 生成html格式结果 profiler stop --format html # 默认情况下,arthas使用3658端口,则可以打开: http://localhost:3658/arthas-output/ 查看到arthas-output目录下面的profiler结果

高级使用

# profiler支持的事件 profiler list # 可以用--event参数来指定 profiler start --event alloc # 恢复采样 profiler resume # 停止采样,不退出profiler profiler suspend # 使用指定文件来保存result profiler stop --file /tmp/result.html # 生成的结果保存到指定目录 profiler start --file /tmp/test.jfr # 生成jfr格式的结果 profiler start --file /tmp/test.jfr profiler stop --format jfr

过滤器

# 只显示指定包下的结果 profiler start --include 'demo.*' # 排除指定的包 profiler start --exclude 'java.*'
💡 火焰图分析技巧:
  • Y轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高
  • X轴表示抽样数,如果一个函数在X轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长
  • 火焰图就是看顶层的哪个函数占据的宽度最大。只要有"平顶",就表示该函数可能存在性能问题

📈 heapdump - 堆内存分析

# 只dump live对象 heapdump --live /tmp/dump.hprof # dump到指定文件 heapdump /tmp/dump.hprof
⚠️ 注意: heapdump 命令会dump堆内存到指定的文件,文件可能会很大。同时会暂停应用一段时间,线上环境请谨慎操作!

🧮 vmtool - JVM工具

利用JVMTI接口,实现查询内存对象,强制GC等功能。

# 获取对象 vmtool --action getInstances --className demo.MathGame # 指定返回结果展示的深度 vmtool --action getInstances --className demo.MathGame -x 2 # 执行表达式 vmtool --action getInstances --className demo.MathGame --express 'instances[0].random.nextInt(10000)' # 强制GC vmtool --action forceGc

⚡ 高级功能

options - 全局开关

查看或设置Arthas全局开关

# 查看所有的options options # 获取option的值 options json-format # 设置option的值 options json-format true # 设置输出结果的展开层次 options expand-level 3
名称 默认值 描述
unsafe false 是否支持对系统级别的类进行增强
dump false 是否支持被增强了的类dump到外部文件中
batch-re-transform true 是否支持批量对匹配到的类执行retransform操作
json-format false 是否以JSON格式输出
expand-level 1 对象属性展开层次
verbose false 是否打印更多详细信息

logger - 查看logger信息

# 查看所有logger信息 logger # 查看指定名字的logger信息 logger -n org.springframework.web # 更新logger level logger --name ROOT --level debug # 指定classloader更新 logger level logger -c 18b4aac2 --name ROOT --level debug

mbean - 查看Mbean信息

# 列出所有Mbean的名字 mbean # 查看Mbean的属性信息 mbean java.lang:type=Threading # 通配符匹配特定的属性字段 mbean java.lang:type=Threading *Count # 使用通配符匹配特定的Mbean mbean java.lang:type=* # 显示MBean的属性和操作信息 mbean -E java.lang:type=Threading

ognl - 执行ognl表达式

# 调用静态函数 ognl '@java.lang.System@out.println("hello")' # 获取静态类的静态字段 ognl '@demo.MathGame@random' # 执行多行表达式,赋值给临时变量,返回一个List ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}' # 获取spring context ognl '#context=@demo.arthas.SpringContextUtils@getApplicationContext(), #context.getBean("helloWorldService")'

🔄 redefine - 热更新代码

推荐使用 retransform 命令。

⚠️ 注意事项:
  • 不允许新增加field/method
  • 正在跑的函数,没有退出不能生效
  • 不支持注解的修改,metadata相关的修改
# 加载外部.class文件,redefine jvm已加载的类 redefine /tmp/Test.class # redefine的.class不能修改、添加、删除类的field和method,包括方法参数、方法名称及返回值 redefine -c 327a647b /tmp/Test.class

🎨 dump - 导出已加载类的字节码

# dump已加载类的字节码文件到特定目录 dump java.lang.String # dump到指定目录 dump -d /tmp/output java.lang.String # 带有classLoader信息 dump -c 327a647b org.springframework.web.servlet.DispatcherServlet

🌐 Web Console 功能

Arthas支持Web Console,用户在attach成功之后,可以直接访问:http://127.0.0.1:3658/

🖥️ Web界面

提供友好的Web界面,可以通过浏览器直接操作

📱 移动端支持

支持手机等移动设备访问

🔄 实时更新

支持实时刷新,查看最新的监控数据

💾 结果导出

支持导出执行结果和分析报告

启用Web Console

# 默认启动会开启web console java -jar arthas-boot.jar # 指定端口启动 java -jar arthas-boot.jar --telnet-port 9999 --http-port 8563 # 只开启web console,不开启telnet java -jar arthas-boot.jar --telnet-port -1 --http-port 8080

Web Console特性

  • 命令自动补全:在Web Console中输入命令时,支持Tab键自动补全
  • 命令历史:支持上下箭头键查看历史命令
  • 结果高亮:执行结果支持语法高亮显示
  • 文件下载:生成的火焰图、堆dump文件等可以直接下载
  • 多会话:支持多个浏览器标签页同时连接
💡 访问路径:
  • Web Console:http://localhost:3658/
  • Arthas Output:http://localhost:3658/arthas-output/
  • Static Files:http://localhost:3658/static/

🔒 安全配置

# 配置用户名密码验证 java -jar arthas-boot.jar --username admin --password admin # 绑定到指定IP java -jar arthas-boot.jar --target-ip 192.168.1.100 # 配置SSL java -jar arthas-boot.jar --ssl
⚠️ 生产环境安全提醒:
  • 建议配置用户名密码验证
  • 限制访问IP范围
  • 使用HTTPS协议
  • 定期检查访问日志

💼 实战案例

案例一:排查CPU使用率过高

场景:生产环境CPU使用率持续过高,需要找出热点方法
# 1. 查看最忙的3个线程 thread -n 3 # 2. 启动CPU火焰图分析 profiler start # 3. 等待一段时间收集数据(如30秒) # ... 等待 ... # 4. 生成火焰图 profiler stop --format html # 5. 针对热点方法进行trace分析 trace com.example.service.HotService hotMethod '#cost > 10'

案例二:排查内存泄漏

场景:应用内存持续增长,怀疑有内存泄漏
# 1. 查看JVM内存使用情况 dashboard # 2. 强制执行GC vmtool --action forceGc # 3. 查看某个类的实例数量 vmtool --action getInstances --className com.example.model.User --express 'instances.size()' # 4. 生成堆dump文件进行详细分析 heapdump --live /tmp/heap.hprof # 5. 持续监控对象创建 watch com.example.model.User '' '{params}' -x 2

案例三:接口响应慢问题排查

场景:某个API接口响应时间过长,需要定位性能瓶颈
# 1. 监控接口方法的执行情况 monitor -c 5 com.example.controller.UserController getUserInfo # 2. 观察方法执行详情,包括参数和返回值 watch com.example.controller.UserController getUserInfo '{params,returnObj,#cost}' '#cost>1000' # 3. trace完整的调用链路 trace com.example.controller.UserController getUserInfo '#cost > 500' # 4. 使用tt记录特定的慢请求 tt -t com.example.controller.UserController getUserInfo '#cost > 1000' # 5. 查看记录的详细信息 tt -i 1000

案例四:线程死锁排查

场景:应用出现线程阻塞,疑似死锁
# 1. 查找阻塞其他线程的线程 thread -b # 2. 查看所有线程状态 thread # 3. 查看特定线程的堆栈信息 thread 123 # 4. 持续监控线程状态变化 dashboard -i 2000 -n 10

案例五:类加载问题排查

场景:出现ClassNotFoundException或ClassCastException
# 1. 查找类是否被加载 sc com.example.model.User # 2. 查看类的详细信息,包括类加载器 sc -d com.example.model.User # 3. 查看类的方法信息 sm com.example.model.User # 4. 反编译类查看源码 jad com.example.model.User # 5. 查看ClassLoader的情况 classloader # 6. 查看ClassLoader的继承关系 classloader -t

🔧 常见问题与故障排除

❌ 连接问题

无法attach到Java进程

可能原因:
  • 目标Java进程不存在
  • 权限不足
  • Java版本不兼容
# 检查Java进程 jps -l # 使用root权限启动 sudo java -jar arthas-boot.jar # 指定Java Home export JAVA_HOME=/usr/lib/jvm/java-8-openjdk java -jar arthas-boot.jar

端口被占用

# 查看端口使用情况 netstat -tulpn | grep 3658 # 指定其他端口启动 java -jar arthas-boot.jar --telnet-port 9999 --http-port 8080

⚠️ 性能问题

命令执行缓慢

优化建议:
  • 使用更精确的类和方法匹配模式
  • 限制输出结果的深度和数量
  • 避免在高频方法上使用trace
  • 合理使用条件表达式过滤
# 限制输出深度 watch com.example.Service method returnObj -x 1 # 使用条件过滤 trace com.example.Service method '#cost > 100' # 限制执行次数 tt -t com.example.Service method -n 10

🛠️ 命令失效问题

增强的类没有生效

# 重置所有增强的类 reset # 重置指定的类 reset com.example.Service # 重新加载类 retransform com.example.Service

找不到方法或类

# 搜索类 sc *Service* # 搜索方法 sm com.example.Service *method* # 查看类的详细信息 sc -d com.example.Service

📋 最佳实践

🎯 精确匹配

使用精确的类名和方法名,避免使用过于宽泛的通配符

⏱️ 限制时间

使用-n参数限制执行次数,避免长时间运行影响性能

🔍 条件过滤

合理使用条件表达式,只关注需要的数据

🧹 及时清理

使用完毕后执行reset命令,清理增强的类

🚀 生产环境使用建议:
  • 在低峰期使用,避免影响业务
  • 使用条件过滤,减少输出量
  • 设置合理的超时时间
  • 及时清理增强的类和缓存
  • 记录操作日志,便于问题追溯