Java 诊断利器之 Arthas 介绍

Arthas(阿尔萨斯) 是阿里巴巴于 2018 年开源的 Java 诊断利器。作为 GitHub 国产 Top5 的 Java 开源项目,已成为商业公司实际上的线上问题排查的首选工具。

Arthas 的核心优势在于:

  • 无需重启应用:通过 Java Agent 动态 attach 到目标 JVM。
  • 零代码侵入:不需修改业务代码即可完成诊断。
  • 功能全面:覆盖类加载、方法追踪、线程分析、内存监控、动态执行等场景。
  • 交互友善:支持命令行 + Web Console 双模式,学习成本低。

本文将详细解析 Arthas 的使用。

本文基于 Arthas 4.10.5 编写。


一、Arthas 快速上手

1.1 安装方式

方式一:在线一键安装(推荐)

# 使用Http1.0请求
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

执行后,Arthas 会自动列出当前主机所有可 attach 的 Java 进程:

[INFO] arthas-boot version: 4.10.5
[INFO] Found existing java process, please choose one and input the serial number of the process, eg: 1. Then hit ENTER.
* [1]: 12345 org.apache.catalina.startup.Bootstrap
  [2]: 67890 com.example.MyApplication

输入序号(如 2),即可连接到目标进程。

方式二:手动下载完整包

适用于无外网环境:

wget https://arthas.aliyun.com/download/latest_version?mirror=aliyun -O arthas.zip
unzip arthas.zip
cd arthas
./as.sh

方式三:Maven 依赖(用于集成测试)

<dependency>
    <groupId>com.taobao.arthas</groupId>
    <artifactId>arthas-agent-attach</artifactId>
    <version>4.10.5</version>
</dependency>

1.2 启动参数详解

参数

说明

默认值

–target-ip

监听 IP

127.0.0.1

–telnet-port

Telnet 端口

3658

–http-port

HTTP/WebConsole 端口

8563

–tunnel-server

Tunnel Server 地址

–app-name

应用名称(用于 Tunnel)

示例:开放远程访问

java -jar arthas-boot.jar --target-ip 0.0.0.0 --telnet-port 3658 --http-port 8563

⚠️ 生产环境提议限制 IP 访问,避免安全风险。

1.3 连接方式

  • 本地连接:直接运行 java -jar arthas-boot.jar
  • 远程连接:telnet <服务器IP> 3658
  • Web Console:浏览器访问 http://<服务器IP>:8563

Web Console 支持语法高亮、命令历史、多标签页,适合复杂操作。


二、基础命令与信息查看

2.1 协助与会话管理

命令

作用

help

显示所有命令协助

help <command>

查看具体命令用法

version

显示 Arthas 版本

session

查看当前会话 ID、启动时间等

quit

/ exit

退出当前会话(Arthas 仍在后台运行)

stop

彻底关闭 Arthas(卸载 agent)

2.2 JVM 全景监控:dashboard

dashboard

输出包含:

  • Memory:堆/非堆内存使用情况
  • GC:Young GC / Full GC 次数与耗时
  • Threads:线程总数、活跃数、Daemon 数
  • Runtime:JVM 启动时间、Uptime
  • Class Loading:已加载类数量

按 Ctrl+C 退出实时刷新。

2.3 线程分析:thread

基础用法

thread          # 列出所有线程
thread <id>     # 查看指定线程堆栈

高级选项

选项

说明

-n N

显示 CPU 使用率 top N 的线程

-b

检测死锁(BLOCKED 状态线程)

-i <ms>

指定采样间隔(默认 100ms)

实战示例

# 找出 CPU 占用最高的 3 个线程
thread -n 3

# 检查是否存在死锁
thread -b

输出示例:

"Thread-5" Id=25 cpuUsage=85.2% RUNNABLE
    at com.example.CpuBurner.run(CpuBurner.java:15)

2.4 JVM 详细信息:jvm

jvm

展示:

  • JVM 版本、供应商
  • 启动参数(-Xmx, -XX:+UseG1GC 等)
  • 内存池详情(Eden、Survivor、Old Gen)
  • GC 统计
  • 系统属性(java.home, user.dir)

2.5 系统属性与环境变量

sysprop                 # 查看所有系统属性
sysprop java.version    # 查看 JDK 版本
sysenv                  # 查看环境变量
sysenv PATH             # 查看 PATH

支持动态修改(慎用):

sysprop user.timezone Asia/Shanghai

2.6 JVM 启动参数:vmoption

vmoption                # 查看所有 JVM 选项
vmoption PrintGC        # 查看 -XX:+PrintGC 是否开启
vmoption PrintGC true   # 动态开启(部分参数支持)

注意:并非所有参数都支持运行时修改。


三、类与类加载器操作

3.1 搜索类:sc(Search Class)

sc *UserController          # 模糊匹配
sc -d com.example.UserDao   # 显示详细信息(类加载器、位置等)
sc -E "com.example..*Service"  # 正则匹配

常用选项:

  • -d:显示详细信息
  • -E:启用正则表达式
  • -c <hash>:指定类加载器 hashcode(用于多 ClassLoader 场景)

3.2 搜索方法:sm(Search Method)

sm com.example.UserService      # 列出所有方法
sm com.example.UserService getUserById  # 查看特定方法签名
sm -d com.example.UserService getUserById  # 显示方法描述符

3.3 反编译:jad

ounter(line
jad com.example.UserService

输出反编译后的 Java 源码,便于理解线上代码逻辑。

若类被混淆或加密(如商业软件),可能反编译失败。

3.4 类加载器分析:classloader

ounter(lineounter(lineounter(lineounter(lineounter(line
classloader                      # 显示类加载器树
classloader -l                   # 列出所有类加载器
classloader -t                   # 以树形结构展示
classloader -c <hash>            # 查看指定加载器加载的资源
classloader -a                   # 列出所有加载的类(慎用,可能卡顿)

典型场景:排查 ClassNotFoundException 或类版本冲突。


四、方法监控与动态追踪(核心功能)

4.1 watch:观察方法入参、返回值、异常

语法

ounter(line
watch <class> <method> '<express>' [condition] [options]

表达式变量

变量

含义

params

参数数组

target

当前对象

returnObj

返回值

throwExp

抛出的异常

#cost

方法执行耗时(微秒)

示例

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
# 观察 getUser 方法的入参和返回值
watch com.example.UserService getUser '{params, returnObj}' -x 2

# 仅当 userId > 1000 时触发
watch com.example.UserService getUser '{params[0]}' 'params[0] > 1000'

# 包含异常情况
watch com.example.UserService getUser '{throwExp}' -f -x 3

选项说明:

  • -x N:展开对象层级(默认 1,提议 2~3)
  • -f:包含异常(默认只成功调用)
  • -s:打印调用栈
  • -n N:执行 N 次后自动退出

4.2 trace:追踪方法调用路径与耗时

trace com.example.OrderService createOrder

输出示例:

+---[0.56ms] com.example.OrderService:createOrder()
    +---[0.21ms] com.example.InventoryService:checkStock()
    +---[0.30ms] com.example.PaymentService:processPayment()
        +---[0.15ms] com.example.ThirdPartyClient:call()

用途:定位性能瓶颈,识别慢方法。

高级用法:

# 追踪子方法(默认只一层)
trace -E com.example.*Service .*  # 正则匹配多个类方法

# 限制耗时 > 10ms 才输出
trace com.example.Service method '#cost > 10000'

4.3 monitor:统计方法调用指标

monitor -c 5 com.example.CacheService get

每 5 秒输出一次统计:

 timestamp            class                     method    total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------
 2025-12-15 22:00:00  CacheService              get       120    118      2     3.2         1.67%

适用于监控接口稳定性。

4.4 stack:打印方法调用栈

stack com.example.UserService updateUser

当 updateUser 被调用时,立即打印完整调用栈,用于定位“谁调用了我”。


五、高级功能与动态干预

5.1 OGNL 表达式:动态执行代码

OGNL(Object-Graph Navigation Language)允许在运行时执行任意 Java 表达式。

基础用法

# 调用静态方法
ognl '@java.lang.System@out.println("Hello")'

# 获取静态字段
ognl '@com.example.Config@MAX_RETRY'

# 修改静态变量(慎用!)
ognl '@com.example.FeatureToggle@setEnabled(true)'

Spring 应用中获取 Bean

ounter(line
ognl '#ctx=@org.springframework.context.support.AbstractApplicationContext@getBean("applicationContext"), #ctx.getBean("userService")'

提示:可通过 sc *ApplicationContext 找到实际上下文类名。

5.2 日志级别动态调整:logger

支持 Logback、Log4j2、JUL。

logger                          # 查看所有 logger
logger --name ROOT --level DEBUG  # 设置根日志为 DEBUG
logger --name com.example --level WARN

无需重启即可开启 debug 日志,排查问题后恢复。

5.3 热更新类:mc + redefine(高危操作!)

仅限开发/测试环境使用!

步骤:

  1. 修改源码(如修复 bug)
  2. 编译 .class 文件
  3. 使用 Arthas 内存编译器(mc)或上传 .class
  4. redefine 替换
# 方式一:使用 mc 编译(需源码)
mc /tmp/UserService.java -d /tmp
redefine /tmp/com/example/UserService.class

# 方式二:直接上传 .class 文件
redefine /opt/fix/UserService.class

限制

  • 不能增减字段/方法
  • 不能修改方法签名
  • 不支持 Lambda、内部类复杂结构

5.4 异步与批处理

  • 后台执行:trace Xxx method &
  • 限制次数:watch Xxx method -n 10
  • 重定向输出(Web Console 支持保存结果)

六、生产环境实战案例

C1:CPU 使用率飙升至 100%

排查步骤

  1. dashboard → 确认 CPU 高
  2. thread -n 3 → 找出高 CPU 线程
  3. thread <tid> → 查看堆栈
  4. jad + trace → 定位具体方法
  5. 发现死循环或正则回溯等问题

解决方案

  • 优化算法
  • 增加超时控制
  • 修复正则表达式

C2:接口响应时间从 50ms 升至 2s

排查步骤

  1. trace com.xxx.Controller handleRequest
  2. 发现 PaymentService.callThirdParty() 耗时 1800ms
  3. watch PaymentService callThirdParty '{params, #cost}'
  4. 发现第三方 API 未设置超时

解决方案

  • 添加 HttpClient 超时配置
  • 增加重试机制

C3:偶发 NullPointerException

排查步骤

  1. watch Xxx method '{params, throwExp}' -f -x 3
  2. 捕获到异常时的参数状态
  3. 发现某字段为空,因上游未校验

解决方案

  • 增加空值校验
  • 完善单元测试

C4:动态开启调试日志

logger --name com.example.payment --level DEBUG
# 复现问题后
logger --name com.example.payment --level INFO

避免重启,快速获取上下文日志。


七、安全、性能与最佳实践

7.1 安全注意事项

  • 权限控制:Arthas 进程必须与目标应用同用户
  • 网络暴露:生产环境禁止 –target-ip 0.0.0.0,应通过 SSH 隧道访问
  • 高危命令
    • ognl:可能执行任意代码
    • redefine:可能导致 JVM 崩溃
    • vmoption:可能影响 GC 行为
  • 审计:提议记录 Arthas 操作日志(可通过 Web Console 集成)

7.2 性能影响评估

命令

性能影响

提议

watch

/trace

中(字节码增强)

加 -n 限制次数

jad

thread -n

classloader -a

高(遍历所有类)

避免使用

redefine

高(类重定义)

仅测试环境

7.3 最佳实践

  1. 先观察,再干预:优先使用 dashboard、thread、trace 等只读命令。
  2. 限制范围:使用 -n、条件表达式缩小监控范围。
  3. 及时退出:长时间运行的 watch/trace 会持续占用资源。
  4. 结合日志:Arthas 与应用日志互补,共同定位问题。
  5. 团队共享:通过 Web Console 或 Tunnel Server 实现多人协作。

八、扩展与生态

8.1 Tunnel Server:聚焦管理

适用于大规模集群:

  • 启动 Tunnel Server(官方提供 Docker 镜像)
  • 客户端启动时指定 –tunnel-server ws://tunnel.example.com:7777
  • Web UI 统一管理所有 Arthas 实例

8.2 与 SkyWalking、Prometheus 集成

  • Arthas 本身不提供指标上报,但可通过脚本定期采集 dashboard 数据
  • 结合 jmx_exporter 实现 JVM 指标监控

8.3 自动化脚本

编写 Arthas 脚本(.arthas 文件):

# diagnose.arthas
dashboard
thread -n 3
sc *Controller

执行:

java -jar arthas-boot.jar -f diagnose.arthas

结语

Arthas 作为一款强劲的 Java 诊断工具,其价值不仅在于功能丰富,更在于它改变了我们排查线上问题的思维方式——从“被动等待日志”转向“主动实时观测”。掌握 Arthas,意味着你拥有了在不重启、不改代码的前提下,深入 JVM 内部的能力。

不过,能力越大,责任越大。务必牢记:生产环境谨慎操作,安全第一


附录:常用命令速查表

场景

命令

查看整体状态

dashboard

CPU 高

thread -n 3

死锁

thread -b

反编译

jad com.xxx.Class

观察方法

watch Xxx method '{params, returnObj}' -x 2

追踪耗时

trace Xxx method

统计调用

monitor -c 5 Xxx method

谁调用了我

stack Xxx method

动态日志

logger –name xxx –level DEBUG

执行代码

ognl '@System@out.println(“test”)'

© 版权声明

相关文章

暂无评论

none
暂无评论...