JVM可视化监控工具Arthas JVM 内存布局是排查线上问题的基础。很多开发者遇到 OutOfMemoryError 时不知道从哪里入手。本文结合实际案例,讲清楚各区域的作用和常见异常,帮你建立排查思路。
安装与启动 curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar [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:系统仪表盘
输出 :
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 $ 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:热更新代码 javac /tmp/Service.java $ redefine /tmp/Service.class
注意 :
不能修改方法签名
不能添加/删除方法
不能修改静态字段
#
7. heapdump:生成堆 dump $ heapdump /tmp/dump.hprof $ heapdump --live /tmp/dump.hprof
#
$ 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 $ 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:接口响应慢 $ thread -n 5 $ trace com.example.Controller getData '#cost>1000' $ watch com.example.Dao slowQuery '{params}' -x 2
#
场景2:线上 Bug 修复 $ jad com.example.Service bugMethod $ redefine /tmp/Service.class $ trace com.example.Service bugMethod
#
场景3:内存泄漏排查 $ dashboard $ vmtool --action getInstances --className com.example.Cache --limit 100 $ heapdump /tmp/dump.hprof
在 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 线上诊断的瑞士军刀,掌握它可以大幅提升线上问题排查效率。
核心要点
堆内存分为年轻代和老年代,年轻代又分为 Eden、Survivor 等区域
栈内存是线程私有的,每个线程都有自己的栈空间
方法区(元空间)存储类信息、常量池等
常见的 OOM 类型:HeapSpace、OutOfMemoryError、StackOverflowError
总结 理解 JVM 内存模型是成为高级 Java 工程师的必备技能。在实际项目中,配置合适的堆内存大小、选择合适的垃圾收集器,都需要对内存布局有清晰的认识。