更新于 2026/05/24

Arthas

Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
通常,本地开发环境无法访问生产环境。如果在生产环境中遇到问题,则无法使用 IDE 远程调试。更糟糕的是,在生产环境中调试是不可接受的,因为它会暂停所有线程,导致服务暂停。
开发人员可以尝试在测试环境或者预发环境中复现生产环境中的问题。但是,某些问题无法在不同的环境中轻松复现,甚至在重新启动后就消失了。
如果您正在考虑在代码中添加一些日志以帮助解决问题,您将必须经历以下阶段:测试、预发,然后生产。这种方法效率低下,更糟糕的是,该问题可能无法解决,因为一旦 JVM 重新启动,它可能无法复现,如上文所述。
Arthas 旨在解决这些问题。开发人员可以在线解决生产问题。无需 JVM 重启,无需代码更改。 Arthas 作为观察者永远不会暂停正在运行的线程。

Arthas官方文档

查cpu高占用

  • dashboard 查看占用最高的线程
  • thread -n 3 查看占用高的线程及其堆栈

查内存高占用

  • oom崩溃的情况无法处理,需要-XX:+HeapDumpOnOutOfMemoryError
    • -XX:HeapDumpPath=/tmp/heapdump.hprof 指定dump文件位置
    • 进程还活着才可以分析
  • vmtool --action forceGc 先fullGc一次
  • dashboard 查看Memory
  • jmap -histo:live <pid> | head -n 20 查看是否有大量自定义对象 一般排名靠前的都是java的基本类型
  • heapdump --live /tmp/dump.hprof 导出文件后拖到idea或者mat软件分析
    • 在合并的路径tab中可以按照实例类型和引用关系找到引用最多对象的实例
    • 在最大对象tab中可以看到对象及其引用的对象的占用并层层展开查看引用关系
    • 保留(Retained)是这个对象及其引用的对象层层递归加起来的总内存占用,主要看这个
      • 计算的是对象的独占对象的内存占用,如果一个object还被其他object引用,则不纳入计算
      • 找到保留大小最大的几个对象,通过引用树找到持有这些对象的实例
    • 浅层(Shallow)是这个对象本身占用的内存,一般只有数组的浅层大小会很大

修改方法逻辑

  • jad --source-only com.example.demo.UserController > /tmp/UserController.java 添加 --lineNumber=false 不显示行号 -d dump文件到目录
  • 编辑补全逻辑
  • mc /tmp/UserController.java -d /tmp 编译成class
  • retransform /tmp/com/example/demo/UserController.class 热重载

查慢方法调用

  • trace com.example.demo.OrderController createOrder -n 1 添加监听
    • -n 1 指定触发次数,方法触发指定次数后自动退出,不添加则会连续监听直到ctrl c
    • 若入参或返回值过长可以输出到文件 文件路径不能使用~ 否则会创建名为~的文件
  • 输出包含方法调用栈以及行号的执行耗时
    • 输出的列表和Map不会展开内容,只会显示size

查方法入参返回值

  • watch com.example.demo.UserService login "{params, returnObj}" -n 1 添加监听
    • -n 1 指定触发次数,方法触发指定次数后自动退出,不添加则会连续监听直到ctrl c
    • 添加 -x 2 展开对象, 展开2刚好够展开Map和List
    • watch com.example.demo.UserService login "{ @com.alibaba.fastjson.JSON@toJSONString(params), @com.alibaba.fastjson.JSON@toJSONString(returnObj) }" -n 1 使用OGNL编写表达式可以输出json格式, 此时不需要-x展开
    • watch com.example.demo.UserService login "{ params, returnObj }" "params[0].name == 'test'" -n 1 使用OGNL编写条件表达式,可以在递归调用等地方过滤不想要收集的方法调用 如果在win等无法输入中文的情况下可以用unicode编码 "'\u6d4b\u8bd5\u540d\u5b57' == params[0]"