Arthas Java 线上诊断与字节码增强
arthas 是阿里开源的 Java 诊断工具,通过 JVM Attach API 附着到目标进程,开启 telnet 3658 / HTTP 8563,在不重启应用的情况下查看线程、内存、GC、类加载器和方法调用。命令大致分四类:dashboard/thread/jvm/memory 看运行时,sc/sm/jad 看类与方法,watch/trace/monitor/tt 看调用,heapdump/profiler/vmtool 做内存与 CPU 采样。
它解决“线上不能重启、日志不够、问题难复现”的困境,常用于 CPU 飙高、接口变慢、线程死锁、内存泄漏、类冲突和值不符合预期的排查。与 jstack/jmap/jcmd 相比,Arthas 提供交互式会话和字节码增强,能按条件观察入参、返回值和异常;它的 profiler 封装了 async-profiler,同时提供更完整的运行时视图。代价是增强有开销、attach 会短暂停顿,生产必须按变更流程使用。
Arthas 默认只绑定 127.0.0.1,telnet 3658、HTTP 8563,会话默认 10800 秒超时;Arthas 进程要与业务 JVM 同用户、同容器、同 PID 命名空间才能 attach。诊断结束用 stop 退出当前会话,用 shutdown 关闭 Arthas 服务端,不要让它长期常驻。
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
java -jar arthas-boot.jar 12345
telnet 127.0.0.1 3658
dashboard -i 5000
thread -n 5
thread -b
thread 12345
jvm
heapdump --live /tmp/app.hprof
第二条命令会列出 Java 进程并提示选择 PID;也可以直接传 PID。thread -n 5 按 CPU 排序取前 5 个线程,thread -b 找阻塞其他线程的锁持有者,thread <id> 看单个线程栈。dashboard 每 5 秒刷新线程、内存、GC 和运行时信息。
sc -d com.example.OrderService
sm com.example.OrderService create
jad --source-only com.example.OrderService
watch com.example.OrderService create '{params, returnObj, throwExp}' -x 2 -n 5
trace com.example.OrderService create '#cost > 100' -n 5
monitor -c 5 com.example.OrderService create
ognl '@java.lang.System@getProperty("java.version")'
profiler start -e cpu
profiler status
profiler stop --format html
stop
watch 在方法调用前后观察指定表达式,-x 2 展开两层属性;trace 统计调用链耗时,#cost > 100 只显示超过 100ms 的调用;monitor 每 5 秒输出一次调用次数、成功率和平均耗时。profiler start 开始采样,profiler stop 生成 HTML 报告。
Unable to open socket file 或 No such process:用户不同、只有 JRE 没有 JDK 工具、容器 PID 命名空间不同、/tmp 不可写或 noexec;先 ps -ef 确认用户,进入目标容器。heapdump --live 还会触发 Full GC 并写出大文件;避开业务高峰,先确认堆大小和磁盘余量。watch/trace/monitor 依赖字节码增强,高 QPS 方法上开销明显;用 -n 限制次数、用 #cost 过滤,结束后 stop 或 reset 还原增强类。sc -d 拿 classloader hash,再用 -c 指定。classloader -t 和 sc -d 核对 hash,增强错类会看不到业务调用。jad 输出是反编译结果,不保证与源码一致或可编译;lambda、内部类和行号会变形,适合定位逻辑,不要直接拿去发布。redefine 不能增删字段/方法、不能改继承关系,且要先 options unsafe true;热替换只适合应急止血,最终仍要发布修复。ognl 修改静态字段同样需要 options unsafe true;shell 里用单引号包住表达式,避免 $ 和引号被提前展开。thread -b 只检测 synchronized 造成的阻塞,找不到不代表没有锁竞争;结合 thread --state BLOCKED、jstack 和 profiler 的 lock 事件。heapdump 默认导出全部对象,--live 只保留存活对象但会先 Full GC;OOM 现场优先依赖 -XX:+HeapDumpOnOutOfMemoryError,不要反复 dump。perf_event_paranoid 和容器权限,必要时改用其他采样方式。--target-ip 0.0.0.0 会把 3658/8563 暴露到网络,Arthas 没有强认证;用 SSH 隧道或防火墙限制,也不要依赖默认会话超时。watch/trace 没有输出时应该检查什么?heapdump --live 与普通 dump 有什么区别,什么时候不该用?sc -d 和 -c 核对。--live 只导出存活对象但会先触发 Full GC;堆很大或业务高峰时不该用,优先靠 OOM 自动 dump。