Arthas 实战线上诊断的瑞士军刀工具篇环境CentOS 7 / JDK 17 / Arthas 4.3.3定位前面 8 篇是手工排查练内功本篇是工具提效——同一批病例换 Arthas 再诊断一遍系列CPU 100% / 锁竞争 / 频繁 Young GC / 切换风暴 / 下游慢 / 池耗尽 / 死锁 / OOM关键词attach、thread -n、thread -b、jad、watch、ognl、heapdump一、Arthas 是什么为什么生产敢用阿里开源的 Java 诊断工具核心能力不重启、不改代码attach 到运行中的 JVM 上做诊断。生产敢用的三个理由attach 机制通过 JVMTI 把 agent 挂进目标 JVM和 jstack/jmap 同一套机制不需要重启服务字节码增强可还原watch/trace是临时增强目标方法的字节码reset一键还原类只读为主绝大多数命令只观测不修改ognl 例外能调方法慎用注意dashboard 里能看到arthas-NettyHttpTelnetBootstrap等线程——Arthas attach 后是住进目标 JVM 的它的线程也会出现在诊断结果里观察者效应。二、上手下载、attach、退出wgethttps://arthas.aliyun.com/arthas-boot.jarjava-jararthas-boot.jar# 列出 Java 进程输入【序号】不是 PID操作命令效果断开但 agent 留在 JVMquit/exit下次 attach 更快但 agent 常驻完全卸载 agentstop不留痕迹生产用完推荐纪律必须用和目标进程相同的用户启动 arthas-bootJDK 大版本别太老。三、手工 vs Arthas 对照表本篇灵魂手工流程前 8 篇Arthas场景top -H→printf %x→jstack grep nidthread -n 3一条搞定A1 CPU 高jstack状态统计找 BLOCKED → grep 锁地址 → 找持锁者thread -b自动揪持锁者B1 锁竞争jstack | grep State | sort | uniq -cthread --state BLOCKED标题行直接印统计状态分布jstat -gc 1000 10两次采样算差值dashboard实时面板A2 GCjmap -histo/jmap -dumpmemory/heapdumpB4 内存翻 jar 包确认代码版本jad反编译线上类版本核对加日志→发版→复现watch/trace免日志观测方法级排查四、实战命令详解全部真实演练① dashboard——综合面板替代 topjstatjstack 三窗口线程区main线程 RUNNABLE 99.75% 直接登顶不用转 16 进制Memory 区heap/eden/old_gen/metaspace 实时水位 GC 次数耗时Runtime 区load、核数、JVM 版本② thread -n 3——CPU 排查一条命令main Id1 cpuUsage100.0% deltaTime200ms time873782ms RUNNABLE at com.jvm.cpu.CpuHighDemo$DeadLoop.main(CpuHighDemo.java:32)cpuUsage deltaTime采样窗口内的瞬时占用time累计 CPU 时间等价 jstack 的cpu直接打印完整堆栈栈顶就是那行死循环③ thread -b——锁竞争的自动破案推荐动线先 dashboard 定方向再 thread -b 抓凶手。第一步dashboard线程区一眼定调——STATE 列一片红色BLOCKED且每个 Worker 的 %CPU 都接近 0读图要点状态红 CPU 低 没人干活全在排队等锁/等池子系。如果是 A1 死循环这里应该是某个线程绿色 RUNNABLE 99% CPU。一个 dashboard 就把干活系和等待系分开了。第二步thread -b精准定位持锁者Worker-15 Id28 TIMED_WAITING at java.lang.Thread.sleep(Native Method) at ...LockContention.lambda$main$0(CpuHighDemo.java:122) - locked java.lang.Object243ef36b ---- but blocks 18 other threads!持锁者 锁地址 受害规模三合一输出——手工时代这是半篇博客的排查量。④ jad——反编译线上代码发错包的克星jad com.jvm.cpu.CpuHighDemo$LockContention输出头部两行隐藏情报ClassLoader: -AppClassLoader ... ← 谁加载的类冲突/元空间问题用 Location: /home/lhadmin/jvm-demo/target/classes/ ← 从哪个物理路径加载的面试题怎么确认线上代码版本的标准答案jad反编译正在运行的类和源码对照。⑤ watch——免日志观测方法布控式watch com.jvm.cpu.CpuHighDemo$LockContention lambda$main$0 {params,returnObj} -x 2 -n 3 # Affect(class count: 1, method count: 1) cost in 110 ms, listenerId: 1{params,returnObj,throwExp}观测入参/返回值/异常-x 2展开深度-n 3抓 3 次自动停配套trace方法内调用链逐跳耗时定位慢在哪一行、monitor -c 5方法调用统计、stack谁调用了这个方法用完reset还原被增强的类⑥ ognl——直接读写运行时对象ognl com.jvm.cpu.CpuHighDemo$LockContentioncounter.get() # Integer[625634] ← 静态变量实时值踩坑实录JDK 9 模块墙ognl ...counter # 直接读对象 → 报错 InaccessibleObjectException: module java.base does not opens java.util.concurrent.atomicOGNL 默认反射序列化整个对象含私有字段JDK 9 模块化拦下。解法不读字段改调 public 方法.get()——这也是生产环境--add-opens参数存在的意义。⑦ heapdump——一条命令导堆但生产纪律不变heapdump /tmp/arthas-dump.hprof # Heap dump file created两个必须说清的点它只是导出变简单了Arthas 的 heapdump 本质就是jmap -dump换皮底层同一个 HotSpot dumpHeap 调用同样 STW、文件同样≈堆大小——别以为换了工具就没代价了。生产环境依然要遵守第 8 篇的纪律低峰期或摘流量后再导只想粗判先用memory等价 jmap -histo不触发 FGC分析还是 MAT/VisualVM 的活heapdump 只负责把堆搬出来支配树、Leak Suspects、引用链分析仍在 MAT/VisualVM 里做完整流程见第 8 篇一句话Arthas 优化的是怎么拿出来不是要不要 STW更不替代怎么分析。五、其他高频命令速查命令干什么面试场景jvmJVM 整体信息快速摸底vmoption查看/动态改 JVM 参数线上能临时开 GC 日志吗→ 能logger动态改日志级别不重启开 DEBUGgetstatic 类名 字段名看静态字段ognl 的简便版读配置开关profiler start/stopasync-profiler 火焰图CPU/内存分配热点性能分析压轴sc -d 类名类的加载信息类冲突排查tt -t 类 方法记录方法调用时空隧道可回放疑难偶发问题六、面试 60 秒话术“线上诊断我用 Arthas它通过 attach 机制挂进 JVM不用重启。CPU 高用thread -n直接拿热点线程堆栈锁问题thread -b自动找持锁者确认代码版本用jad反编译方法级排查用watch/trace免日志观测入参返回值和逐跳耗时运行时的静态值用ognl读堆问题heapdump导出来 MAT 分析。增强类用完reset还原退出用stop卸载 agent 不留痕迹。手工的 top/jstack/jstat 命令链我也熟——那是理解原理Arthas 是生产提效。”口诀热点 -n、找锁 -b、版本 jad、观测 watch、读值 ognl、导堆 heapdumpattach 来、stop 走reset 还原不留痕。