Arthas启动与常用的命令(一)

发布时间 2023-06-07 00:00:11作者: 乐之者v

arthas 有什么用?

Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。

以下是官方文档提到的 arthas 的作用。

当你遇到以下类似问题而束手无策时, Arthas 可以帮助你解决。

  • 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?

  • 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?

  • 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?

  • 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!

  • 是否有一个全局视角来查看系统的运行状况?

  • 有什么办法可以监控到JVM的实时运行状态?

  • 怎么快速定位应用的热点,生成火焰图?

  • Arthas 支持JDK 6+,支持Linux/Mac/Winodws,采用命令行交互模式,同时提供丰富的 Tab 自动补
    全功能,进一步方便进行问题的定位和诊断。

安装arthas

详情见: https://www.cnblogs.com/expiator/p/17454838.html

启动示例类:

math-game 是arthas 自带的一个示例类。可以启动后,用于测试。

curl -O https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar

启动 arthas

java -jar arthas-boot.jar

选择 java 进程,输入对应的序号,比如 1,然后按Enter,就可以了。

[INFO] JAVA_HOME: D:\jdk8\jre
[INFO] arthas-boot version: 3.6.9
[INFO] Process 19440 already using port 3658
[INFO] Process 19440 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 19440 math-game.jar
  [2]: 19744 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [3]: 21952 com.intellij.database.remote.RemoteJdbcServer
  [4]: 9120 org.jetbrains.jps.cmdline.Launcher

查看 dashboard

输入 dashboard,按回车/enter,会展示当前进程的信息,按ctrl+c可以中断执行。

watch

能够方便的观察到指定函数的调用情况。能观察到的范围为:返回值抛出异常入参,通过编写 OGNL 表达式进行对应变量的查看。

在使用 Intellij Idea 进行调试时,有时会用watch() 查看变量的值,arthas的 watch命令作用类似,而且更加强大。

  • watch常用的参数:
参数名称 参数说明
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
express 观察表达式
condition-express 条件表达式,满足条件表达式才查看
-b 在方法调用之前观察,before
-e 在方法异常之后观察,exception
-s 在方法返回之后观察,success
-f 在方法结束之后(正常返回和异常返回)观察,finish
-e 开启正则表达式匹配,默认为通配符匹配
-x 指定输出结果的属性遍历深度,默认为 1
  • 查看方法的入参、属性、返回值:

默认情况下,会查看方法的入参、属性、返回值。

watch  包的路径.类名 方法名  "{params, target, returnObj}"

包的路径,一般就是类的代码里面的 package 路径。

假设 某个类的代码里面显示 package com.example.demo; 那么包的路径就是com.example.demo,

如果不确定包的路径,也可以用 *. 匹配,比如 Demo类,就是 *.Demo。

params: 就是方法参数

target: 就是类的属性

returnObj: 返回值。

  • 查看方法的参数、返回值。(非常实用)
watch demo.MathGame primeFactors "{params,returnObj}"
  • 查看方法的返回值
watch  包的路径.类名 方法名 returnObj

示例:

watch demo.MathGame primeFactors returnObj
  • watch使用 -x

-x参数,指遍历深度,默认为1,如果无法查出数值,可以尝试加大遍历深度。

示例:

遍历深度,默认为1。

result=@ArrayList 后面的结果分别对应 "{params, target, returnObj}"

结果只能看到 result 结果中有多少个参数,没法看到参数的具体值。

[arthas@19440]$ watch demo.MathGame primeFactors -x 1
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 14 ms, listenerId: 2
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2023-06-06 00:09:00; [cost=0.355ms] result=@ArrayList[
    @Object[][isEmpty=false;size=1],
    @MathGame[demo.MathGame@15f550a],
    null,
]

当遍历深度,修改为 2后,显示如下,可以看到 入参数是 1 (也就是下文的 @Integer[1] ), 返回结果的@ArrayList 也能看到list 里面具体的数值(也就是下文的 2,2,2,19,29,47)。

[arthas@19440]$ watch demo.MathGame primeFactors -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 22 ms, listenerId: 3
method=demo.MathGame.primeFactors location=AtExit
ts=2023-06-06 00:09:03; [cost=0.1013ms] result=@ArrayList[
    @Object[][
        @Integer[1],
    ],
    @MathGame[
        random=@Random[java.util.Random@6b2d4a],
        illegalArgumentCount=@Integer[46006],
    ],
    @ArrayList[
        @Integer[2],
        @Integer[2],
        @Integer[2],
        @Integer[19],
        @Integer[29],
        @Integer[47],
    ],
]
  • 只查看满足条件表达式的:

示例,"params[0]<0", 表示只有第一个参数小于0时,才查看数据。

[arthas@19440]$ watch demo.MathGame primeFactors "{params,returnObj}" "params[0]<0" -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 21 ms, listenerId: 2
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2023-06-06 22:47:07; [cost=0.102ms] result=@ArrayList[
    @Object[][
        @Integer[-81071],
    ],
    null,
]
  • 查看异常:

通过 "{params,throwExp}" 查看异常。

[arthas@19440]$  watch demo.MathGame primeFactors "{params,throwExp}" -e -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 22 ms, listenerId: 4
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2023-06-06 22:52:41; [cost=0.1559ms] result=@ArrayList[
    @Integer[-49317],
    java.lang.IllegalArgumentException: number is: -49317, need >= 2
        at demo.MathGame.primeFactors(MathGame.java:46)
        at demo.MathGame.run(MathGame.java:24)
        at demo.MathGame.main(MathGame.java:16)
,
]
  • 根据耗时查看:

#cost>200(单位是ms)表示只有当耗时大于 200ms 时才会输出,过滤掉执行时间小于 200ms 的调用;

$ watch demo.MathGame primeFactors '{params, returnObj}' '#cost>200' -x 2
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 66 ms.
ts=2018-12-03 19:40:28; [cost=2112.168897ms] result=@ArrayList[
    @Object[][
        @Integer[1],
    ],
    @ArrayList[
        @Integer[5],
        @Integer[428379493],
    ],
]
  • 观察当前对象中的属性

如果想查看函数运行前后,当前对象中的属性,可以使用target关键字,代表当前对象

$ watch demo.MathGame primeFactors 'target'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 52 ms.
ts=2018-12-03 19:41:52; [cost=0.477882ms] result=@MathGame[
    random=@Random[java.util.Random@522b408a],
    illegalArgumentCount=@Integer[13355],
]

然后使用target.field_name访问当前对象的某个属性

$ watch demo.MathGame primeFactors 'target.illegalArgumentCount'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 67 ms.
ts=2018-12-03 20:04:34; [cost=131.303498ms] result=@Integer[8]
ts=2018-12-03 20:04:35; [cost=0.961441ms] result=@Integer[8]


退出 arthas

  • exit

如果只是退出当前的连接,可以用quit或者exit命令。

Attach 到目标进程上的 arthas 还会继续运行,端口会保持开放,下次连接时可以直接连接上。

  • stop

关闭 Arthas 服务端,所有 Arthas 客户端全部退出。

停止已存在的Arthas实例:

 java -jar arthas-client.jar 127.0.0.1 3658 -c "stop"

参考资料:

https://blog.csdn.net/lydms/article/details/125238249
https://arthas.aliyun.com/doc/watch.html