1. 为什么选Arthas:一次线上事故的解法
先讲一段真实经历。去年年中,我们有个核心接口在夜间低峰期偶尔会报超时,监控面板上的P99从300毫秒突然跳到5秒,持续几分钟后又自己恢复。告警群里值班同事轮流上去看日志、看GC、看CPU,折腾了两天也没定位到根因。最让人头疼的是,这个问题只在生产环境偶发,测试环境怎么压都压不出来,而生产环境又不允许随便停服、加日志、重启验证。后来是靠着Arthas在线上直接trace慢调用链,才锁定到一段在低并发时表现正常、在高并发下会触发锁竞争的资源初始化代码。那次之后,Arthas就成了我们团队线上问题排查的标配工具。
Arthas是阿里巴巴开源的一款Java诊断工具,定位非常明确:在不需要重启应用、不需要额外部署Agent组件的前提下,对运行中的JVM进行实时诊断。它解决的是Java后端开发者最头疼的一类问题——线上环境出了问题,但你没有足够的现场信息去复现和定位。对于正在跑着业务的Java进程,Arthas可以帮你做这些事情:查看类加载信息、反编译线上代码、监控方法调用参数和返回值、追踪方法级别的调用链耗时、查看线程栈、采样分析CPU热点、在线修改运行中的逻辑等等。它的适用人群很清晰:所有做Java服务端开发、需要跟生产环境打交道的人。不管你是初入行的开发,还是带团队的技术负责人,只要有过线上问题定位困难的经历,Arthas都值得你花半天时间系统学一遍。
网上关于Arthas的教程其实不少,但大多是命令手册的翻译版,告诉你怎么用watch、怎么用trace,却很少解释这些命令背后的原理、适用场景以及真正的进阶玩法。所以这篇内容,我根据自己的实际使用经验,把Arthas从启动到常用命令、再到OLGN表达式和批处理脚本的进阶玩法串一遍,重点讲清楚那些手册里不写、但实际排查中非常有用的细节。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 启动与连接:从下载到attach,那些拦路虎
2.1 一个反直觉的事实:listener模式与attach机制
很多人第一次接触Arthas,以为它跟SkyWalking那样的Agent一样,需要在应用启动时通过-javaagent参数挂进去。实际上Arthas是启动时动态attach到目标JVM上的,不需要预先在应用启动参数里做任何配置。它启动后会以独立进程的方式运行,跟你正在诊断的Java进程通过socket通信。这个设计的好处显而易见:不需要提前规划、不需要重发应用,任何时刻你发现线上有问题,都可以用Arthas临时接入进去。
但这也带来一个容易踩坑的点——Arthas运行的目标是“附着”到另一个JVM上,而JVM的attach机制依赖于能否拿到目标进程的PID。Arthas拿到PID的方式,默认是通过jps工具枚举本机所有Java进程。如果这一步就卡住了,后面所有功能都无从谈起。
2.2 "arthas启动无法获取jps进程"的排查链路
这个热搜词下面的问题,我见过太多次了,而且绝大多数不是Arthas本身的问题。根据我的排查经验,按下面这个顺序逐个检查,基本能解决99%的情况。
第一,检查Arthas跟目标JVM是否运行在同一用户下。JDK8及以下版本中,jps获取进程信息依赖的是/tmp/hsperfdata_<username>目录,每个用户只能看到自己启动的JVM。如果你用root用户启动Arthas,去看一个普通用户启动的Java进程,jps里就是看不到的。解决方案很简单:切换到进程所属用户再启动Arthas,或者赋予/tmp/hsperfdata_*目录的访问权限。
第二,检查目标JVM是否开启了共享内存。有个JVM参数叫-XX:+PerfDisableSharedMem,生产环境如果为了性能优化加了这参数,jps就完全无法感知这个进程。这种情况不用纠结,直接用ps -ef | grep java找到进程PID,然后执行java -jar arthas-boot.jar <PID>绕过进程枚举直接attach。
第三,容器环境的PID命名空间隔离问题。在Docker/K8s里,你通过docker exec进到容器内执行jps,看到的是容器内的PID,而用宿主机上的Arthas去attach,看到的却是宿主机PID。这两者可能对不上。最稳妥的做法是在容器内执行Arthas,或者在宿主机上用docker inspect --format {{.State.Pid}} <container>查出进程的真实PID,再手动指定给Arthas。
2.3 下载与attach失败的兜底手段
Arthas的下载地址是官方GitHub Releases,或者直接
