Arthas - 初识阿里开源诊断工具,零基础快速上手

Arthas - 初识阿里开源诊断工具,零基础快速上手

👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕Arthas这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


文章目录

  • Arthas - 初识阿里开源诊断工具,零基础快速上手 🚀
    • 什么是 Arthas?🤔
    • 为什么需要 Arthas?💡
    • 快速安装与启动 🛠️
      • 1. 下载并启动 Arthas Boot
    • 核心命令一览 🧰
    • 场景一:查看 JVM 基本信息 🖥️
      • 使用 `dashboard` 查看实时仪表盘
      • 使用 `sysprop` 查看系统属性
      • 使用 `vmtool` 获取堆内对象
    • 场景二:排查接口响应慢问题 🐢➡️🐇
      • 示例 Java 代码
      • 使用 `trace` 命令追踪方法调用
    • 场景三:查看方法入参和返回值 🔍
      • 使用 `watch` 命令监控方法执行
    • 场景四:分析线程阻塞问题 🧱
      • 模拟线程阻塞代码
      • 使用 `thread` 命令分析线程状态
    • 场景五:反编译字节码查看源码 🔁
      • 使用 `jad` 反编译类
    • 场景六:动态修改日志级别 📝
      • 使用 `logger` 命令修改日志级别
    • 场景七:监控方法调用次数与成功率 📈
      • 使用 `monitor` 命令监控方法
    • 场景八:生成火焰图分析性能瓶颈 🔥
      • 使用 `profiler` 生成火焰图
    • 使用 Mermaid 图表理解 Arthas 架构 🧩
    • 高级技巧:结合 OGNL 表达式操作对象 💪
      • 什么是 OGNL?
      • 示例:获取静态字段值
      • 调用静态方法
      • 创建对象并测试逻辑
    • 场景九:类加载问题排查 🧱
      • 使用 `sc` 查找已加载的类
    • 场景十:在线修复简单 Bug(谨慎使用)🪄
      • 使用 `redefine` 热更新类
    • Web Console:图形化操作界面 🖼️
      • 启动 Web Terminal
    • 最佳实践建议 ✅
    • 常见问题解答 ❓
      • Q:Arthas 会影响线上性能吗?
      • Q:支持 JDK 版本有哪些?
      • Q:能否诊断 Native 方法?
      • Q:是否支持 Spring Boot Actuator 替代?
    • 总结 🎯
    • 结语 🌟

Arthas - 初识阿里开源诊断工具,零基础快速上手 🚀

在现代 Java 应用开发与运维的世界里,线上问题排查始终是每个开发者绕不开的挑战。当系统突然变慢、接口响应超时、内存占用飙升,而你又无法轻易重启服务时,传统的日志分析和本地调试手段往往显得力不从心。这时,一款强大、轻量、无需重启应用即可实时诊断的工具就显得尤为重要。

Arthas就是这样一款由阿里巴巴开源的 Java 诊断工具,它被誉为“Java 程序员的瑞士军刀”。无论你是开发、测试还是运维工程师,只要你在处理 Java 应用,Arthas 都能帮你快速定位问题,提升效率。🎯

本文将带你从零开始认识 Arthas,通过实际代码示例、命令详解和可视化图表,让你在短时间内掌握这款神器的核心能力,并能在真实项目中灵活运用。


什么是 Arthas?🤔

Arthas 是一个基于命令行的 Java 诊断工具,专为解决生产环境中难以复现的问题而设计。它支持在不修改代码、不重启 JVM 的前提下,对正在运行的 Java 进程进行动态监控、方法追踪、性能分析和故障排查。

它的核心优势包括:

  • 🔍无需侵入代码:不需要添加任何依赖或修改业务逻辑。
  • 实时诊断:可以即时查看线程状态、调用栈、方法执行耗时等。
  • 📊丰富的命令集:提供数十个实用命令,覆盖大部分诊断场景。
  • 💻交互式控制台:类似 Linux Shell,支持自动补全、历史命令、管道操作。
  • 🌐远程诊断支持:可通过 Web Console 实现远程连接与操作。

官方文档地址:https://arthas.aliyun.com/doc


为什么需要 Arthas?💡

想象一下这个场景:

你的线上订单系统突然出现大量超时,用户投诉不断。你查看日志发现某个orderService.createOrder()方法执行时间异常,但日志中没有详细的入参和返回值,也无法复现问题。此时你有两个选择:

  1. 修改代码,增加详细日志,重新打包部署 → 至少需要 30 分钟,期间问题持续发生。
  2. 使用 Arthas 直接连接到线上 JVM,实时 trace 这个方法的调用路径、耗时分布、参数值 → 几分钟内定位瓶颈。

显然,第二种方式更高效,也更安全。这就是 Arthas 存在的意义 ——让诊断变得像写 SQL 查询一样简单


快速安装与启动 🛠️

Arthas 提供了多种安装方式,最常用的是通过curlwget下载启动脚本。

1. 下载并启动 Arthas Boot

打开终端,执行以下命令:

curl-Ohttps://arthas.aliyun.com/arthas-boot.jarjava-jararthas-boot.jar

更多安装方式详见官方指南:https://arthas.aliyun.com/doc/install-detail.html

执行后,Arthas 会列出当前机器上所有正在运行的 Java 进程:

* [1]: 12345 com.example.DemoApplication [2]: 67890 org.apache.catalina.startup.Bootstrap

输入对应的编号(如1),即可连接到目标进程。

连接成功后,你会看到熟悉的提示符:

[arthas@12345]$

恭喜!你现在已进入 Arthas 控制台,可以开始诊断之旅了!🎉


核心命令一览 🧰

Arthas 提供了超过 40 个命令,覆盖了从基础信息查询到高级性能分析的各个方面。下面我们通过几个典型场景,逐步深入学习这些命令的使用。


场景一:查看 JVM 基本信息 🖥️

当你连接到一个 Java 进程后,第一步通常是了解它的运行环境。

使用dashboard查看实时仪表盘

[arthas@12345]$ dashboard

该命令会展示一个实时更新的控制面板,包含:

  • 当前时间
  • JVM 运行时长
  • CPU 使用率
  • 内存使用情况(堆、非堆)
  • 线程总数及状态分布
  • GC 情况
  • 加载的类数量

这是一个非常直观的入口,帮助你快速判断系统是否处于异常状态。

使用sysprop查看系统属性

[arthas@12345]$ sysprop

列出所有的 JVM 系统属性,例如java.versionuser.homefile.encoding等。你也可以查看单个属性:

[arthas@12345]$ sysprop java.version

输出:

java.version: 17.0.8

使用vmtool获取堆内对象

[arthas@12345]$ vmtool--actiongetInstances--classNamejava.lang.String--limit5

该命令会获取堆中前 5 个String对象的实例,适用于分析内存中某些类的分布情况。


场景二:排查接口响应慢问题 🐢➡️🐇

假设我们有一个 Spring Boot 应用,其中某个 REST 接口/api/order响应缓慢。我们可以使用 Arthas 来追踪方法调用链。

示例 Java 代码

先来看一段模拟的业务代码:

@RestControllerpublicclassOrderController{@GetMapping("/api/order")publicStringcreateOrder(@RequestParamStringuserId){try{Thread.sleep(2000);// 模拟耗时操作}catch(InterruptedExceptione){Thread.currentThread().interrupt();}return"Order created for user: "+userId;}}

这是一个典型的“睡眠 2 秒”来模拟数据库查询或远程调用的场景。

现在我们想确认到底是谁在耗时,以及参数是什么。

使用trace命令追踪方法调用

[arthas@12345]$ trace *OrderController createOrder

当你再次访问/api/order?userId=U12345时,Arthas 会输出如下结果:

`---ts=2025-04-05 10:20:30;thread_name=http-nio-8080-exec-1;id=0x1;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader `---[1998.12ms] com.example.OrderController:createOrder() `---[1998.01ms] sleep()

可以看到,createOrder方法耗时约 2 秒,几乎全部消耗在Thread.sleep()上。这说明问题出在模拟的延迟操作中。

💡 提示:trace支持通配符匹配类名和方法名,非常适合不知道完整类路径时使用。


场景三:查看方法入参和返回值 🔍

有时候我们不仅想知道方法耗时,还想看看传了什么参数,返回了什么结果。

使用watch命令监控方法执行

[arthas@12345]$watch*OrderController createOrder'{params, returnObj}'-x3

解释一下参数:

  • {params, returnObj}:表示我们要观察的表达式,即参数和返回对象。
  • -x 3:展开对象层级,最多显示 3 层嵌套。

再次请求接口后,输出如下:

method=com.example.OrderController.createOrder location=AtExit ts=2025-04-05 10:25:10 id=0x2 params=[["U12345"]] returnObj="Order created for user: U12345"

太棒了!我们现在清楚地看到了输入参数是"U12345",返回值也符合预期。

你还可以加上条件过滤,比如只监控特定用户的调用:

[arthas@12345]$watch*OrderController createOrder returnObj'params[0]=="U12345"'

这样只有当userId == "U12345"时才会触发监听。


场景四:分析线程阻塞问题 🧱

线程死锁或长时间阻塞是线上常见的性能瓶颈。Arthas 提供了强大的线程分析能力。

模拟线程阻塞代码

@ServicepublicclassBlockService{privatefinalObjectlock1=newObject();privatefinalObjectlock2=newObject();publicvoiddeadlockDemo(){newThread(()->{synchronized(lock1){System.out.println("Thread-1 got lock1");try{Thread.sleep(1000);}catch(InterruptedExceptione){}System.out.println("Thread-1 trying to get lock2");synchronized(lock2){System.out.println("Thread-1 got lock2");}}}).start();newThread(()->{synchronized(lock2){System.out.println("Thread-2 got lock2");try{Thread.sleep(1000);}catch(InterruptedExceptione){}System.out.println("Thread-2 trying to get lock1");synchronized(lock1){System.out.println("Thread-2 got lock1");}}}).start();}}

这段代码极有可能导致死锁。虽然不一定每次都会发生,但它足以用来演示如何检测潜在风险。

使用thread命令分析线程状态

[arthas@12345]$ thread

该命令列出所有线程的基本信息,包括 ID、名称、状态和 CPU 占比。

重点关注状态为BLOCKEDWAITING的线程。

进一步查看具体线程堆栈:

[arthas@12345]$ thread15

输出可能类似于:

"Thread-1" Id=15 BLOCKED on java.lang.Object@6bdf8c8d owned by "Thread-2" Id=16 at com.example.BlockService.lambda$deadlockDemo$0(BlockService.java:15) - blocked on java.lang.Object@6bdf8c8d - locked java.lang.Object@6bdf8c8d at java.base@17.0.8/java.lang.Thread.run(Thread.java:833)

如果你怀疑存在死锁,可以直接使用:

[arthas@12345]$ thread-b

Arthas 会自动检测是否存在死锁,并报告涉及的线程和锁。

输出示例:

Found one Java-level deadlock: ============================= "Thread-1": waiting to lock monitor 0x00007f8a4c003c58 (object 0x000000076bdf8c8d, a java.lang.Object), which is held by "Thread-2" "Thread-2": waiting to lock monitor 0x00007f8a4c006b98 (object 0x000000076bdf8ca5, a java.lang.Object), which is held by "Thread-1"

这是非常宝贵的诊断信息,能够帮助你迅速定位并发问题根源。


场景五:反编译字节码查看源码 🔁

有时候你连接到一个线上服务,却找不到对应的源码,或者怀疑代码被篡改。这时可以使用jad命令反编译类文件。

使用jad反编译类

[arthas@12345]$ jad *OrderController

输出将是该类的 Java 源码形式(基于字节码还原):

publicclassOrderController{publicOrderController(){}@GetMapping(value="/api/order")publicStringcreateOrder(StringuserId){try{Thread.sleep(2000L);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}return"Order created for user: "+userId;}}

你甚至可以将结果保存到文件:

[arthas@12345]$ jad *OrderController>/tmp/OrderController.java

这对于审计、调试第三方库或分析混淆代码非常有用。


场景六:动态修改日志级别 📝

很多项目使用 SLF4J + Logback 或 Log4j2 作为日志框架。当出现问题时,往往需要提高日志级别以便查看更多细节。传统做法是修改配置文件并重启服务,但现在你可以用 Arthas 动态调整。

使用logger命令修改日志级别

[arthas@12345]$ logger--nameROOT--levelDEBUG

这条命令将根日志器的日志级别设置为DEBUG

查看当前日志配置:

[arthas@12345]$ logger

输出会列出所有 logger 名称、级别、附加器等信息。

你也可以针对特定包设置级别:

[arthas@12345]$ logger--namecom.example.service--levelTRACE

无需重启,立即生效!这对临时排查问题非常友好。


场景七:监控方法调用次数与成功率 📈

有时我们需要统计某个方法被调用了多少次,失败率是多少。这在微服务架构中尤其重要。

使用monitor命令监控方法

[arthas@12345]$ monitor-c5*OrderController createOrder
  • -c 5表示每 5 秒统计一次。

输出示例:

timestamp class method total success fail cost(avg) 2025-04-05 10:40:00 OrderController createOrder 3 3 0 1987.23 2025-04-05 10:40:05 OrderController createOrder 2 2 0 2001.45

这个表格清晰地展示了单位时间内的调用量、成功率和平均耗时,可用于初步判断接口稳定性。


场景八:生成火焰图分析性能瓶颈 🔥

火焰图(Flame Graph)是一种可视化性能分析工具,能直观展示哪些方法占用了最多 CPU 时间。

Arthas 内置了profiler命令,可生成兼容标准格式的火焰图。

使用profiler生成火焰图

[arthas@12345]$ profiler start

启动后,Arthas 开始采样 JVM 的执行栈。

等待一段时间(比如 30 秒),然后停止:

[arthas@12345]$ profiler stop

默认会生成一个html文件,你可以下载并在浏览器中打开查看火焰图。

你也可以指定输出路径:

[arthas@12345]$ profiler stop--output/data/logs/flamegraph.html

此外,还支持导出为jfr格式供 JMC 分析:

[arthas@12345]$ profiler stop--formatjfr--output/data/logs/record.jfr

更多关于火焰图的原理,请参考:http://www.brendangregg.com/flamegraphs.html


使用 Mermaid 图表理解 Arthas 架构 🧩

为了更好地理解 Arthas 的工作原理,我们可以通过 Mermaid 图表来展示其内部结构。

双向通信

WebSocket 连接

用户终端

Arthas Client

通信方式

Telnet

HTTP/WebSocket

JVM 进程

Arthas Agent

ByteBuddy 字节码增强

Java Attach API 注入

JMX MBean 暴露

外部工具

Web Console

如上图所示:

  • Arthas 通过Java Attach API将自身注入到目标 JVM 中,成为一个Agent
  • Agent 利用ByteBuddy对目标类进行字节码增强,实现方法拦截、耗时统计等功能。
  • 用户通过Telnet 或 HTTP连接到 Agent,发送命令并接收结果。
  • 支持 Web Console,便于团队协作和远程诊断。

这种非侵入式的设计保证了 Arthas 在生产环境中的安全性与稳定性。


高级技巧:结合 OGNL 表达式操作对象 💪

Arthas 支持使用 OGNL(Object-Graph Navigation Language)表达式来动态访问和操作 Java 对象。这使得你可以像写脚本一样操控运行时数据。

什么是 OGNL?

OGNL 是一种功能强大的表达式语言,允许你通过字符串访问对象的属性、调用方法、创建集合等。

示例:获取静态字段值

假设我们有一个类:

publicclassGlobalConfig{publicstaticStringENV="prod";publicstaticMap<String,String>settings=newHashMap<>();static{settings.put("timeout","5000");settings.put("retry","3");}}

使用getstatic命令读取静态字段:

[arthas@12345]$ getstatic com.example.GlobalConfig ENV

输出:

field: ENV @String[prod]

读取 map 中的值:

[arthas@12345]$ getstatic com.example.GlobalConfig settings'settings.get("timeout")'

输出:

@String[5000]

调用静态方法

[arthas@12345]$ ognl'@com.example.GlobalConfig@reloadSettings()'

这会调用GlobalConfig.reloadSettings()静态方法。

创建对象并测试逻辑

[arthas@12345]$ ognl'#obj=new com.example.User(), #obj.setName("test"), #obj.getName()'

虽然不能真正改变业务逻辑,但在调试时非常有用。


场景九:类加载问题排查 🧱

Java 中的类加载机制复杂,常见的问题包括:

  • 同名类来自不同 jar 包
  • 类找不到(ClassNotFoundException)
  • 方法不存在(NoSuchMethodError)

Arthas 提供了classloadersc命令来帮助分析。

使用sc查找已加载的类

[arthas@12345]$ sc *OrderController

输出:

CLASS-LOADER HASH CLASS-QNAME +-sun.misc.Launcher$AppClassLoader@18b4aac2 18b4aac2 com.example.OrderController

你可以看到这个类是由哪个 ClassLoader 加载的。

进一步查看 ClassLoader 的层次结构:

[arthas@12345]$ classloader

输出类似:

name numberOfInstances loadedCountTotal BootstrapClassLoader 1 3456 PlatformClassLoader 1 120 AppClassLoader 1 450

如果遇到类冲突,可以使用:

[arthas@12345]$ sc-dcom.example.util.StringUtils

查看具体的加载路径和来源 jar 包。


场景十:在线修复简单 Bug(谨慎使用)🪄

虽然不推荐在生产环境随意修改代码,但在极端情况下,Arthas 提供了redefine命令,允许你热替换类定义。

使用redefine热更新类

前提是你已经编译好了新的.class文件。

[arthas@12345]$ redefine /tmp/FixedOrderController.class

该命令会替换 JVM 中原有的类定义,不会触发初始化逻辑,且仅限于方法体变更,不能修改字段或方法签名。

⚠️ 警告:此操作有风险,可能导致不可预知的行为,建议仅用于紧急修复且充分测试后使用。


Web Console:图形化操作界面 🖼️

除了命令行,Arthas 还提供了 Web Console,支持通过浏览器连接到 Arthas Agent,进行可视化操作。

启动 Web Terminal

在启动 Arthas 时添加--tunnel-server参数:

java-jararthas-boot.jar --tunnel-server'ws://*:7777'--agent-id abcdefg

然后访问:

👉 https://arthas.aliyun.com/doc/web-console.html

输入对应的agent-id即可连接。

Web Console 支持多用户协作、命令历史、结果高亮、图形化 dashboard 等特性,特别适合团队共享诊断会话。


最佳实践建议 ✅

在使用 Arthas 时,遵循以下最佳实践可以最大化其价值并降低风险:

  1. 权限控制:生产环境应限制可连接 Arthas 的 IP 地址,避免未授权访问。
  2. 操作记录:开启命令审计日志,记录谁在什么时候执行了什么命令。
  3. 避免高频采样tracemonitor等命令有一定性能开销,不要长时间开启。
  4. 结合监控系统:将 Arthas 与 Prometheus、Grafana 等工具结合,形成完整可观测体系。
  5. 定期培训:组织团队成员学习 Arthas 常用命令,提升整体排障能力。

常见问题解答 ❓

Q:Arthas 会影响线上性能吗?

A:轻微影响。大多数命令采用异步采样或事件驱动,只有在触发时才会产生少量开销。但像trace这类深度追踪命令应慎用。

Q:支持 JDK 版本有哪些?

A:支持 JDK 6 及以上版本,包括 OpenJDK、Oracle JDK、Alibaba Dragonwell 等主流发行版。

Q:能否诊断 Native 方法?

A:不能。Arthas 基于字节码增强,只能拦截 Java 方法调用。

Q:是否支持 Spring Boot Actuator 替代?

A:不完全替代。Actuator 提供健康检查、指标暴露等标准化接口;Arthas 更偏向于临时性、交互式的深度诊断。两者互补。


总结 🎯

Arthas 作为一款由阿里开源的 Java 诊断利器,彻底改变了我们对线上问题的认知方式。它让我们不再局限于“看日志 → 猜问题 → 改代码 → 重发版”的低效循环,而是能够直接深入 JVM 内部,实时观测、精准定位、快速解决。

通过本文的学习,你应该已经掌握了:

  • 如何安装和连接 Arthas
  • 使用dashboardthreadtracewatch等核心命令
  • 分析性能瓶颈、线程阻塞、类加载等问题
  • 利用 OGNL 和 Web Console 提升效率
  • 在真实项目中安全、有效地使用 Arthas

官方完整文档:https://arthas.aliyun.com/doc

无论你是刚入门的新手,还是经验丰富的架构师,Arthas 都值得你花时间去深入了解。把它加入你的工具箱,让它成为你应对线上危机时最可靠的伙伴。


结语 🌟

技术的发展从未停止,而我们的学习也不应止步。Arthas 不仅仅是一个工具,它代表了一种面向运行时的思维方式—— 我们不仅要写出正确的代码,更要学会如何观察它、理解它、优化它。

愿你在每一次深夜救火中,都能从容不迫;在每一个棘手 Bug 面前,都有 Arthas 为你照亮前路。🌙💡

Happy diagnosing! 😊


🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍点赞、📌收藏、📤分享给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨