# 方式1: 下载 arthas jar
https://alibaba.github.io/arthas/arthas-boot.jar
# 方式2: 下载 arthas 压缩包, 解压到指定目录, 如: /home/arthas/
https://github.com/alibaba/arthas/releases/download/arthas-all-3.1.4/arthas-3.1.4-bin.zip
# 启动 arthas
λ java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.1.4
[INFO] Process 1240 already using port 3658
[INFO] Process 1240 already using port 8563
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 1240 com.answer.ai.Application
[2]: 3232
[3]: 23064 org.jetbrains.jps.cmdline.Launcher
1
# 通过 web console 浏览器访问
http://127.0.0.1:8563/
# 退出arthas
# 如果只是退出当前的连接,可以用quit或者exit命令。Attach到目标进程上的arthas还会继续运行,端口会保持开放,下次连接时可以直接连接上。
quit
exit
# 如果想完全退出arthas,可以执行stop命令。
stop
Arthas_3.1.4下载链接
当前系统的实时数据面板
# 当前进程的信息
dashboard
# 执行 10 次
dashboard -n 10
# 每隔 2000ms 执行一次, 默认: 5000ms
dashboard -i 2000
查看当前线程信息,查看线程的堆栈
# 显示所有线程的信息
thread
# 当前最忙的前N个线程并打印堆栈
thread -n 3
# 显示指定线程的运行堆栈
thread <id>
# 找出当前阻塞其他线程的线程(目前只支持找出synchronized关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持)
thread -b
# 指定采样时间间隔
thread -n 3 -i 1000
反编译指定已加载类的源码
# 反编译指定类
jad com.answer.ai.config.XloProperties
# 反编绎时只显示源代码
jad --source-only com.answer.ai.config.XloProperties
# 反编译指定函数
jad com.answer.ai.config.XloProperties setIeso
# 将反编译代码重定向到文件
jad --source-only com.answer.ai.config.XloProperties > ./Ai.java
查看JVM已加载的类信息
# 查看 com.answer.* 包下已加载的类信息
sc com.answer.*
# -d: 输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。如果一个类被多个ClassLoader所加载,则会出现多次
sc -d com.answer.ai.util.XloUtil
# -f: 输出当前类的成员变量信息(需要配合参数-d一起使用)
sc -d -f com.answer.ai.util.XloUtil
查看已加载类的方法信息
sm(Search-Method)
命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到。
# 查看 XloUtil 类中所有方法信息
sm com.answer.ai.util.XloUtil
# 查看 XloUtil 类中以 un 开头的方法信息
sm com.answer.ai.util.XloUtil un*
# 查看 XloUtil 类中 unzip 方法信息
sm com.answer.ai.util.XloUtil unzip
# -d: 展示每个方法的详细信息
sm -d com.answer.ai.util.XloUtil
sm -d com.answer.ai.util.XloUtil un*
sm -d com.answer.ai.util.XloUtil unzip
方法执行数据观测。 让你能方便的观察到指定方法的调用情况。能观察到的范围为:返回值
、抛出异常
、入参
,通过编写 OGNL 表达式进行对应变量的查看。
watch 命令定义了4个观察事件点, 即: -b 方法调用前, -e 方法异常后, -s 方法返回后, -f 方法结束后(默认打开)
# 观察方法出参和返回值. -x: 指定输出结果的属性遍历深度, 默认为 1
watch com.answer.ai.controller.OcrController asyncAnalysis "{params,returnObj}" -x 3
# 观察方法入参. 对比前一个例子,返回值为空(事件点为方法执行前,因此获取不到返回值)
watch com.answer.ai.controller.OcrController asyncAnalysis "{params,returnObj}" -x 2 -b
# 同时观察方法调用前和方法返回后. -n 2: 表示只执行两次
watch com.answer.ai.controller.OcrController asyncAnalysis "{params,returnObj}" -x 2 -s -n 2
# -e: 表示抛出异常时才触发
watch com.answer.ai.controller.OcrController asyncResultGet '{params[0]}' -e -x 2
# 抛出异常时打印一次信息. 异常信息的变量是: throwExp
watch com.answer.ai.controller.OcrController asyncResultGet '{throwExp}' -e -x 3
# 按照耗时进行过滤. 只有当耗时大于20ms时才会输出,过滤掉执行时间小于200ms的调用
watch com.answer.ai.controller.OcrController asyncAnalysis '{params, returnObj}' '#cost>20' -x 2
# 观察当前对象中的属性. 如果想查看方法运行前后,当前对象中的属性,可以使用target关键字,代表当前对象
watch com.answer.ai.controller.OcrController asyncAnalysis 'target'
# 访问当前对象的某个属性(eg: requestId)
watch com.answer.ai.controller.OcrControllcAnalysis 'target.requestId'
# 异步挂起任务, 当存在异常时写入日志
watch com.answer.ai.controller.OcrController asyncAnalysis '{params,returnObj,throwExp}' -n 5 -x 3 'throwExp != null' > exception.log &
PS: 挂起任务使用 jobs 命令查看当前挂起的任务, kill job_id 指令杀死任务
方法执行监控
# 监控 asyncAnalysis 方法的执行
monitor com.answer.ai.controller.OcrController asyncAnalysis
# 每隔 5 秒统计一次. -c: 统计周期,默认值为 60 秒
monitor com.answer.ai.controller.OcrController asyncAnalysis -c 5
# 监控 OcrController 类中的所有方法. -n: 统计 5 次后退出
monitor com.answer.ai.controller.OcrController * -c 30 -n 5
# 挂起监控, 查看监控日志: cat /tmp app.log
monitor com.answer.ai.controller.OcrController * -c 5 > app.log &
# 使用 jobs 命令查看当前挂起的任务, kill job_id 指令杀死任务
输出形式
timestamp class method total success fail avg-rt(ms)
--------------------------------------------------------------------------------------------------------------------------------------------------
2020-06-03 16:58:48 com.answer.ai.controller.OcrController asyncAnalysis 1 1 0 2216.13
dump 已加载类的 bytecode 到特定目录
# dump XloUtil 类到指定目录
dump com.answer.ai.util.XloUtil
# dump com.answer.ai.util 包下的所有类到指定目录
dump com.answer.ai.util.*
# -d: 指定输出目录
dump -d ./ com.answer.ai.util.XloUtil
dump java heap, 类似jmap命令的heap dump功能
# dump到临时文件
heapdump
# dump到指定文件
heapdump ./dump.hprof
# 只dump live对象
heapdump --live ./dump.hprof
输出当前方法被调用的调用路径
# 监控当前方法的调用路径
stack com.answer.ai.util.JacksonUtil parseObject
# -n: 执行次数限制, 达到次数后退出
stack com.answer.ai.util.JacksonUtil parseObject -n 2
需要调用接口并且接口中会调用到监控的方法
方法内部调用路径,并输出方法路径上的每个节点上耗时
trace com.answer.ai.controller.OcrController asyncAnalysis
# -j: 过滤掉jdk的函数
trace -j com.answer.ai.controller.OcrController asyncAnalysis
# #cost: 方法执行耗时, 只会展示耗时大于 50ms 的调用路径,有助于在排查问题的时候,只关注异常情况
trace -j com.answer.ai.controller.OcrController asyncAnalysis '#cost > 50'
trace
能方便的帮助你定位和发现因 RT 高而导致的性能问题缺陷,但其每次只能跟踪一级方法的调用链路。
记录下指定方法每次调用的入参和返回信息。 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
# 记录下当前方法的每次调用环境现场
tt -t com.answer.ai.controller.OcrController asyncAnalysis
# 查看具体某个 INDEX 的调用信息, INDEX: 为返回的表格的 时间片段记录编号(index) 字段
tt -i <INDEX>
# 检索调用记录
tt -l
# 筛选出 asyncAnalysis 方法的调用信息
tt -s 'method.name=="asyncAnalysis"'
tt -t
结果表格字段说明
表格字段 | 字段解释 |
---|---|
INDEX | 时间片段记录编号,每一个编号代表着一次调用,后续tt还有很多命令都是基于此编号指定记录操作,非常重要。 |
TIMESTAMP | 方法执行的本机时间,记录了这个时间片段所发生的本机时间 |
COST(ms) | 方法执行的耗时 |
IS-RET | 方法是否以正常返回的形式结束 |
IS-EXP | 方法是否以抛异常的形式结束 |
OBJECT | 执行对象的hashCode() ,注意,曾经有人误认为是对象在JVM中的内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体 |
CLASS | 执行的类名 |
METHOD | 执行的方法名 |
全局开关
# 查看全局开关信息
options
# 打开执行结果存日志功能, ${user.home}/logs/arthas-cache/result.log
options save-result true
查看,更新VM诊断相关的参数
# 查看所有的option
vmoption
# 查看指定的option
vmoption PrintGC
# 更新指定的option
vmoption PrintGC true