一、核心命令:trace

1. 基本用法

trace <类全限定名> <方法名>

示例:追踪UserServicegetUser方法

trace com.example.UserService getUser

输出示例

---[10.0ms] com.example.UserService:getUser()    
  +---[5.0ms] com.example.UserRepository:findById()    
     ---[5.0ms] com.example.UserConverter:toDTO()

2. 高级参数

(1) 过滤耗时

trace com.example.UserService getUser '#cost > 50'

仅显示耗时超过50ms的调用。

(2) 跳过JDK方法

trace com.example.UserService getUser --skipJDKMethod true

排除JDK内部方法(如java.util.*),减少噪声。

(3) 指定调用深度

trace com.example.UserService getUser -n 3

限制追踪的调用深度为3层。

3. 特殊场景

(1) 追踪构造函数

trace com.example.MyClass <init>

(2) 追踪静态方法

trace com.example.MyClass staticMethod

(3) 追踪重载方法

trace com.example.MyClass myMethod "java.lang.String,int"

通过参数类型指定具体方法。

二、实战步骤

场景:分析接口/user/info的耗时瓶颈

  1. 定位高耗时线程
dashboard

查看线程状态,识别高CPU/内存线程。

  1. 追踪方法调用链
trace com.example.UserController getUserInfo '#cost > 50' --skipJDKMethod true
  1. 结合watch查看参数
watch com.example.UserService queryUserInfo '{params, returnObj}' -x 3 -n 5

捕获方法参数和返回值。

三、输出结果解析

  • #cost:方法执行时间(毫秒)。
  • ts:时间戳,标识调用发生时间。
  • 调用链:自上而下展开,子方法缩进表示层级。
  • 高亮部分:最耗时的调用会被自动标注(如红色字体)。

四、注意事项

  1. 性能影响
    • trace命令会增加应用负载,建议在非高峰期使用。
    • 避免在生产环境长期开启。
  2. 权限问题
    • 确保Arthas进程与目标应用有相同权限(如Linux用户)。
  3. 结果过滤
    • 使用条件表达式(如#cost > 10)避免输出过多无效数据。

五、替代方案

1. 结合watch命令

watch com.example.UserService getUser '{params, #cost}' -x 2 -n 5

同时查看参数和耗时。

2. 使用profiler生成火焰图

profiler start# 执行目标操作profiler stop --format html

生成火焰图可视化方法耗时(需Arthas版本支持)。

六、常见问题

  1. source is null for getProperty错误
    • 确保方法存在且参数正确,避免追踪不存在的方法。
  2. 输出结果为空
    • 检查目标方法是否被实际调用。
    • 调整条件表达式(如降低#cost阈值)。
  3. JDK方法干扰
    • 使用--skipJDKMethod true排除干扰。

通过上述方法,您可以精准定位方法内各步骤的耗时瓶颈,优化应用性能。