【Arthas】从类加载、代码调试、系统监控到性能分析的一站式解决方案
Arthas Java诊断工具,通过命令组合,可以高效解决线上问题,无需重启或重新部署应用
·
Arthas 是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。
当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到 JVM 的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
- 怎样直接从 JVM 内查找某个类的实例?
以下是针对每个问题使用 Arthas 的解决方案和具体操作步骤:
1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
方法:
- 查看类加载信息:使用
sc命令查看类的加载路径和类加载器。 - 检查类路径问题:确认类是否被多个版本加载或路径错误。
具体步骤:
# 查看类的加载信息(替换为你的类名)
sc com.example.YourClass
# 输出示例:
[Loaded com.example.YourClass from file:/path/to/your.jar]
解决类异常问题:
- 如果类找不到或版本冲突,检查
sc输出的路径是否正确。 - 如果类被多次加载,可能需要排查依赖冲突(如 Maven/Gradle 依赖)。
2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
方法:
- 反编译查看字节码:使用
jad命令反编译当前类,确认代码是否生效。 - 跟踪方法执行:使用
trace命令确认方法是否被调用。
具体步骤:
# 反编译当前类的代码(替换为你的类名)
jad com.example.YourClass
// 输出(反编译后的代码片段):
public void saveUser(User user) {
// 如果这里没有新代码,说明未生效
user.setName("oldName"); // 旧代码
// 新代码未出现,如 user.setName("newName");
}
# 跟踪方法执行(替换为你的方法)
trace com.example.YourClass yourMethod
# 跟踪方法执行:
arthas> trace com.example.UserService saveUser -n 1
# 输出(未触发):
[TRACE] com.example.UserService.saveUser(User)
No matched method invoked during 10 seconds.
解决思路:
- 如果反编译的代码与预期不符,说明代码未正确部署。
- 如果
trace未触发,说明代码路径未被调用,需检查逻辑分支。
3. 遇到问题无法线上 debug,难道只能通过加日志再重新发布吗?
方法:
- 实时监控变量:使用
watch命令在方法内监控变量值。 - 动态追踪方法调用:使用
trace或stack命令分析调用链。
具体步骤:
# 监控方法参数和返回值(替换为你的方法)
watch com.example.YourClass yourMethod '{returnObj -> returnObj}'
# 输出
[INFO] watched method [process], total trigger count: 1
param0: {"userId": "123", "data": "corrupted"}
returnObj: null
cost: 15 ms
# 跟踪方法调用栈
trace com.example.YourClass yourMethod -e
# 输出
[TRACE] com.example.DataProcessor.process(Data)
at com.example.MainApplication.handleRequest(MainApplication.java:23)
at com.example.HttpServer.lambda$handleRequest\$0(HttpServer.java:45)
解决思路:
- 无需重新部署,直接在线上分析变量和调用链。
- 结合
thread命令查看线程状态,排查死锁或阻塞问题。
4. 线上遇到某个用户的数据处理有问题,但线上无法 debug,线下无法重现!
方法:
- 过滤特定用户参数:使用
watch命令结合条件表达式,只触发特定用户的数据。 - 记录调用堆栈:使用
stack命令捕获异常堆栈。
具体步骤:
# 监控特定用户ID的调用(假设参数是第1个)
watch com.example.YourClass yourMethod '{-> args[0]}' -c 'args[0].equals("problem_user_id")'
# 过滤特定用户ID的调用
arthas> watch com.example.UserProcessor processUser '{-> args[0]}' -c 'args[0].equals("problem_user_123")'
# 当用户id匹配
[INFO] watched method [processUser], total trigger count: 1
args[0]: problem_user_123
args[1]: {"data": "corrupted"}
# 捕获异常堆栈
stack -n 100
# 假设异常
java.lang.NullPointerException: data is null
at com.example.UserProcessor.processUser(UserProcessor.java:32)
解决思路:
- 通过条件表达式过滤出目标用户的调用,分析参数和执行路径。
- 如果有异常,用
stack查看堆栈信息定位问题。
5. 是否有一个全局视角来查看系统的运行状况?
方法:
- 实时系统监控:使用
dashboard命令查看 JVM 核心指标。 - 线程状态分析:使用
thread命令查看线程状态。
具体步骤:
# 查看实时系统指标(CPU、GC、线程等)
dashboard
# 输出实时更新
------- JVM Info -------
JVM Uptime: 1d 3h 22m 15s
CPU Usage: 85% (System), 75% (Process)
Memory: 20G/32G (Heap), 4G/8G (Non-Heap)
GC: Young GC 120 times, Old GC 5 times
Threads: 230 threads (Daemon: 150, Alive: 230)
------- ClassLoader -------
Loaded: 12,345 classes
Unloaded: 123 classes
------- Recent Exceptions -------
NullPointerException x5 in last 10s
# 查看线程状态
thread
# 输出
TID Name State Blocked by
12345 http-nio-8080-exec-10 RUNNABLE
67890 pool-1-thread-3 WAITING (parking)
解决思路:
dashboard提供全局视角,快速发现 CPU/内存/GC 异常。thread可查看线程阻塞、死锁或高 CPU 消耗的线程。
6. 有什么办法可以监控到 JVM 的实时运行状态?
方法:
- JVM 核心指标:使用
jvm命令查看内存、GC、类加载等信息。 - GC 分析:使用
gc命令监控 GC 次数和耗时。
具体步骤:
# 查看 JVM 内存、GC、类加载等信息
jvm
# 输出
JVM Args: -Xms32g -Xmx32g -XX:+UseG1GC
Memory:
Heap:
init = 34359738368(32.0GB)
used = 21474836480(20.0GB)
committed = 34359738368(32.0GB)
max = 34359738368(32.0GB)
Non-Heap:
init = 2555904(2.44MB)
used = 3858328(3.68MB)
committed = 4456448(4.25MB)
max = 1772979712(1.65GB)
GC:
Young Count: 120
Young Time: 12000ms
Old Count: 5
Old Time: 5000ms
# 实时监控 GC 情况
gc
# 输出
GC Monitor:
Young GC: 120 times, 12s (avg 100ms)
Old GC: 5 times, 5s (avg 1s)
解决思路:
- 通过
jvm快速定位内存泄漏或类加载问题。 gc命令可分析 Full GC 是否频繁,辅助调优。
7. 怎么快速定位应用的热点,生成火焰图?
方法:
- 热点分析:使用
hotspot命令定位 CPU 瓶颈。 - 生成火焰图:使用
flame命令生成火焰图。
具体步骤:
# 定位热点方法(默认采样 10 秒)
hotspot
# 输出
Total CPU(s): 120.5
Rank Self CPU(ms) Total CPU(ms) Method
1 45.6 80.2 com.example.SlowService.processData()
2 30.1 30.1 java.util.zip.Deflater.deflateBytes()
# 生成火焰图(保存为 svg 文件)
flame > hotspot.svg
解决思路:
hotspot输出 Top-N 的热点方法,直接定位性能瓶颈。- 火焰图(flame graph)可视化调用栈,快速识别嵌套调用问题。
8. 怎样直接从 JVM 内查找某个类的实例?
方法:
- 查找类实例:使用
sc和obj命令组合查找实例。 - 统计实例数量:使用
obj -c统计实例个数。
具体步骤:
# 查找类的所有实例(替换为你的类名)
sc -d com.example.YourClass | grep "identityHashCode"
# 输出类似:identityHashCode=123456
# 查看实例详情(替换为 identityHashCode)
obj 123456
# 输出
com.example.User@123456
userId: 123
name: "John Doe"
data: {"status": "active"}
# 统计实例数量
obj -c com.example.YourClass
# 输出
Total instances of com.example.User: 15
解决思路:
- 通过
sc -d获取类的实例对象地址。 - 使用
obj查看实例的字段和引用,排查内存泄漏或状态问题。
总结
| 问题类型 | 关键命令 | 作用描述 |
|---|---|---|
| 类加载问题 | sc | 查看类加载路径和类加载器 |
| 代码未生效 | jad, trace | 反编译代码,跟踪方法调用 |
| 实时调试 | watch, trace, stack | 监控变量、方法调用和异常堆栈 |
| 用户数据问题 | watch (条件表达式) | 过滤特定用户数据 |
| 全局系统监控 | dashboard, thread | 实时查看 JVM 指标和线程状态 |
| JVM 状态监控 | jvm, gc | 分析内存、GC 情况 |
| 性能热点分析 | hotspot, flame | 定位 CPU 瓶颈,生成火焰图 |
| 查找对象实例 | sc -d, obj | 查找类实例并查看详细信息 |
安装 Arthas:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
输入 help 查看所有命令,结合实际场景灵活使用!
更多推荐




所有评论(0)