JVM可视化监控工具Arthas

JVM可视化监控工具Arthas

JVM 内存布局是排查线上问题的基础。很多开发者遇到 OutOfMemoryError 时不知道从哪里入手。本文结合实际案例,讲清楚各区域的作用和常见异常,帮你建立排查思路。

安装与启动

# 在线安装
curl -O https://arthas.aliyun.com/arthas-boot.jar

# 启动
java -jar arthas-boot.jar

# 选择要诊断的 Java 进程
[INFO] arthas-boot version: 3.x.x
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 12345 /app/myapp.jar
[2]: 67890 org.apache.catalina.startup.Bootstrap
1

核心命令

#

1. dashboard:系统仪表盘

$ dashboard

输出

ID   NAME                      GROUP    PRIORITY STATE    %CPU  TIME   INTERRUPTED DAEMON
12 AsyncAppender-Worker main 5 WAITING 0.0 0:0 false true
...

Memory used total max usage GC
heap 256M 512M 4096M 6.25% gc.g1_young_generation.count 100
g1_eden_space 100M 200M - 50.00% gc.g1_young_generation.time 500ms
g1_old_gen 150M 300M 4096M 3.66%
g1_survivor_space 6M 12M - 50.00%

#

2. thread:线程诊断

# 查看所有线程
$ thread

# 查看最忙的5个线程
$ thread -n 5

# 查看指定线程
$ thread 12

# 查看死锁
$ thread -b

# 查看线程状态统计
$ thread --state

#

3. trace:方法耗时追踪

# 追踪方法的入参和返回值
$ trace com.example.Service getOrder '#cost>100' -n 5

# 只追踪异常
$ trace com.example.Service getOrder '#cost>100' --skipJDKMethod false

# 多层追踪
$ trace -E com.example.Service|com.example.Dao getOrder

输出

`---ts=2024-06-13 10:00:00;thread_name=http-nio-8080-exec-1;id=12;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@1234
`---[50.234ms] com.example.Service:getOrder()
+---[5.123ms] com.example.Dao:queryById()
+---[40.456ms] com.example.Client:fetchRemote() # 这里耗时最长
`---[4.655ms] com.example.Mapper:insertLog()

#

4. watch:方法执行数据观测

# 查看方法入参和返回值
$ watch com.example.Service getOrder '{params,returnObj}' -x 2

# 查看异常
$ watch com.example.Service getOrder '{params,throwExp}' -e

# 查看方法执行前后的对象字段
$ watch com.example.User setName '{target,name,params,returnObj}' -b -s -x 2

参数

  • -b:方法执行前
  • -s:方法执行后
  • -e:方法异常后
  • -x 2:展开层级

#

5. jad:反编译代码

# 反编译类
$ jad com.example.Service

# 反编译方法
$ jad com.example.Service getOrder

# 反编译并保存
$ jad --source-only com.example.Service > /tmp/Service.java

#

6. redefine:热更新代码

# 1. 修改 Java 文件
# 2. 编译为 class
javac /tmp/Service.java

# 3. 热加载
$ redefine /tmp/Service.class

注意

  • 不能修改方法签名
  • 不能添加/删除方法
  • 不能修改静态字段

#

7. heapdump:生成堆 dump

# 生成堆 dump
$ heapdump /tmp/dump.hprof

# 只 dump live 对象
$ heapdump --live /tmp/dump.hprof

#

8. vmtool:强制 GC、获取实例

# 强制 GC
$ vmtool --action forceGc

# 获取类的所有实例
$ vmtool --action getInstances --className com.example.User --limit 10

# 执行表达式
$ vmtool --action getInstances --className java.lang.String \
--express 'instances.length'

#

9. tt:方法执行时空隧道

# 记录方法调用
$ tt -t com.example.Service getOrder

# 查看记录
$ tt -l

# 重放第1000次调用
$ tt -p -i 1000

# 查看调用入参和返回值
$ tt -i 1000 -w '{params, returnObj}'

#

10. profiler:生成火焰图

# 开始采样
$ profiler start

# 查看状态
$ profiler status

# 停止并生成火焰图
$ profiler stop --file /tmp/flamegraph.html

# 指定采样事件
$ profiler start --event alloc # 内存分配
$ profiler start --event lock # 锁竞争

实战场景

#

场景1:接口响应慢

# 1. 找到处理请求的线程
$ thread -n 5

# 2. 追踪方法耗时
$ trace com.example.Controller getData '#cost>1000'

# 3. 定位到具体方法后,查看入参
$ watch com.example.Dao slowQuery '{params}' -x 2

#

场景2:线上 Bug 修复

# 1. 反编译确认代码
$ jad com.example.Service bugMethod

# 2. 修改本地代码并编译

# 3. 热更新
$ redefine /tmp/Service.class

# 4. 验证修复
$ trace com.example.Service bugMethod

#

场景3:内存泄漏排查

# 1. 查看内存使用
$ dashboard

# 2. 获取可疑类的实例
$ vmtool --action getInstances --className com.example.Cache --limit 100

# 3. 查看对象引用链
$ heapdump /tmp/dump.hprof
# 用 MAT 分析

在 Spring Boot 中集成

<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-spring-boot-starter</artifactId>
<version>3.6.7</version>
<scope>runtime</scope>
</dependency>
arthas:
agent-id: myapp
tunnel-server: ws://127.0.0.1:7777/ws

总结

命令 用途
dashboard 查看系统整体状态
thread 线程诊断
trace 方法耗时追踪
watch 观测方法数据
jad 反编译
redefine 热更新
heapdump 堆内存 dump
vmtool 强制 GC、获取实例
tt 方法调用记录与重放
profiler 火焰图

Arthas 是 Java 线上诊断的瑞士军刀,掌握它可以大幅提升线上问题排查效率。

核心要点

  1. 堆内存分为年轻代和老年代,年轻代又分为 Eden、Survivor 等区域

  2. 栈内存是线程私有的,每个线程都有自己的栈空间

  3. 方法区(元空间)存储类信息、常量池等

  4. 常见的 OOM 类型:HeapSpace、OutOfMemoryError、StackOverflowError

总结

理解 JVM 内存模型是成为高级 Java 工程师的必备技能。在实际项目中,配置合适的堆内存大小、选择合适的垃圾收集器,都需要对内存布局有清晰的认识。


   转载规则


《JVM可视化监控工具Arthas》 小乐 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录