👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕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()方法执行时间异常,但日志中没有详细的入参和返回值,也无法复现问题。此时你有两个选择:
- 修改代码,增加详细日志,重新打包部署 → 至少需要 30 分钟,期间问题持续发生。
- 使用 Arthas 直接连接到线上 JVM,实时 trace 这个方法的调用路径、耗时分布、参数值 → 几分钟内定位瓶颈。
显然,第二种方式更高效,也更安全。这就是 Arthas 存在的意义 ——让诊断变得像写 SQL 查询一样简单。
快速安装与启动 🛠️
Arthas 提供了多种安装方式,最常用的是通过curl或wget下载启动脚本。
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.version、user.home、file.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 占比。
重点关注状态为BLOCKED或WAITING的线程。
进一步查看具体线程堆栈:
[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-bArthas 会自动检测是否存在死锁,并报告涉及的线程和锁。
输出示例:
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 图表来展示其内部结构。
如上图所示:
- 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 提供了classloader和sc命令来帮助分析。
使用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 时,遵循以下最佳实践可以最大化其价值并降低风险:
- 权限控制:生产环境应限制可连接 Arthas 的 IP 地址,避免未授权访问。
- 操作记录:开启命令审计日志,记录谁在什么时候执行了什么命令。
- 避免高频采样:
trace、monitor等命令有一定性能开销,不要长时间开启。 - 结合监控系统:将 Arthas 与 Prometheus、Grafana 等工具结合,形成完整可观测体系。
- 定期培训:组织团队成员学习 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
- 使用
dashboard、thread、trace、watch等核心命令 - 分析性能瓶颈、线程阻塞、类加载等问题
- 利用 OGNL 和 Web Console 提升效率
- 在真实项目中安全、有效地使用 Arthas
官方完整文档:https://arthas.aliyun.com/doc
无论你是刚入门的新手,还是经验丰富的架构师,Arthas 都值得你花时间去深入了解。把它加入你的工具箱,让它成为你应对线上危机时最可靠的伙伴。
结语 🌟
技术的发展从未停止,而我们的学习也不应止步。Arthas 不仅仅是一个工具,它代表了一种面向运行时的思维方式—— 我们不仅要写出正确的代码,更要学会如何观察它、理解它、优化它。
愿你在每一次深夜救火中,都能从容不迫;在每一个棘手 Bug 面前,都有 Arthas 为你照亮前路。🌙💡
Happy diagnosing! 😊
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍点赞、📌收藏、📤分享给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨