【工具使用】【Arthas】平时经常使用到的命令

1  前言

Arthas,应该大家都用过吧,比如我最近项目 uat 的时候,要查看某些请求比较耗时,查看耗时在哪些地方,再比如一些配置变量值配置的对不对尤其跟一些第三方交互的时候,配置的对不对需要实时查看校验下等,都可以通过Arthas 查看。

Arthas 地址:使用文档   Arthas 的下载:使用下载

Arthas 最贴合的就是 JVM,所以如果你还不了解 JVM 的话,建议先把 JVM 的一些基本知识比如一些类信息、运行时数据区、垃圾回收等先有个认识。因为 Arthas 其实就类似是 JVM 的监控甚至高于监控能动态加载类来更改业务执行逻辑,所以先知道 JVM 是什么,才能更好的理解 Arthas 都对哪些进行了监控并做了哪些增强可以到达什么效果哈。

至于 Arthas 的原理,貌似是使用的 Java Agent、Attach API 以及类似 ASM的字节码修改等实现的,这方面我暂时还没深入的去了解过哈= =,等了解透彻后续会单独来写哈。

本文仅结合官网通过示例,来记录平时经常用到的,方便查看总结哈。

2  Arthas

2.1  表达式核心变量

主要用于表达式的一些提取哈:

变量名变量解释
loader 本次调用类所在的 ClassLoader
clazz 本次调用类的 Class 引用
method 本次调用方法反射引用
target 本次调用类的实例
params 本次调用参数列表,这是一个数组,如果方法是无参方法则为空数组
returnObj 本次调用返回的对象。当且仅当 isReturn==true 成立时候有效,表明方法调用是以正常返回的方式结束。如果当前方法无返回值 void,则值为 null
throwExp 本次调用抛出的异常。当且仅当 isThrow==true 成立时有效,表明方法调用是以抛出异常的方式结束。
isBefore 辅助判断标记,当前的通知节点有可能是在方法一开始就通知,此时 isBefore==true 成立,同时 isThrow==false 和 isReturn==false,因为在方法刚开始时,还无法确定方法调用将会如何结束。
isThrow 辅助判断标记,当前的方法调用以抛异常的形式结束。
isReturn 辅助判断标记,当前的方法调用以正常返回的形式结束。

所有变量都可以在表达式中直接使用,如果在表达式中编写了不符合 OGNL 脚本语法或者引入了不在表格中的变量,则退出命令的执行;用户可以根据当前的异常信息修正条件表达式观察表达式。

2.2  dashboard

查看当前系统的实时数据面板 这个命令可以全局的查看jvm运行状态,比如内存和cpu占用情况,(详细可以看该命令官方文档以及参数说明哈):

  • ID: Java 级别的线程 ID,注意这个 ID 不能跟 jstack 中的 nativeID 一一对应。
  • NAME: 线程名
  • GROUP: 线程组名
  • PRIORITY: 线程优先级, 1~10 之间的数字,越大表示优先级越高
  • STATE: 线程的状态
  • CPU%: 线程的 cpu 使用率。比如采样间隔 1000ms,某个线程的增量 cpu 时间为 100ms,则 cpu 使用率=100/1000=10%
  • DELTA_TIME: 上次采样之后线程运行增量 CPU 时间,数据格式为
  • TIME: 线程运行总 CPU 时间,数据格式为分:秒
  • INTERRUPTED: 线程当前的中断位状态
  • DAEMON: 是否是 daemon 线程

Java 8 之后支持获取 JVM 内部线程 CPU 时间,这些线程只有名称和 CPU 时间,没有 ID 及状态等信息(显示 ID 为-1)。 通过内部线程可以观测到 JVM 活动,如 GC、JIT 编译等占用 CPU 情况,方便了解 JVM 整体运行状况。

  • 当 JVM 堆(heap)/元数据(metaspace)空间不足或 OOM 时,可以看到 GC 线程的 CPU 占用率明显高于其他的线程。
  • 当执行trace/watch/tt/redefine等命令后,可以看到 JIT 线程活动变得更频繁。因为 JVM 热更新 class 字节码时清除了此 class 相关的 JIT 编译结果,需要重新编译。

JVM 内部线程包括下面几种:

  • JIT 编译线程: 如 C1 CompilerThread0C2 CompilerThread0
  • GC 线程: 如GC Thread0G1 Young RemSet Sampling
  • 其它内部线程: 如VM Periodic Task ThreadVM ThreadService Thread

2.3  thread

线程运行情况,(详细可以看该命令官方文档以及参数说明哈):

2.3.1  查看最忙的几个线程

# 查看最忙的前 1 个线程
thread -n 1

2.3.2  查看阻塞其他线程的线程

# 查看目前只支持找出 synchronized 关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持。
thread -b

2.4  watch

让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值抛出异常入参,通过编写 OGNL 表达式进行对应变量的查看,(详细可以看该命令官方文档以及参数说明哈)这个比较常用:

2.4.1  查看方法的入参、出参

# 比如我这里的支付 controller
# -x 2表示参数的深度=2 -n 1表示匹配 1次
# -x 默认为1
# -n 不写的话 会一直输出 调用1次方法就打1次 所以建议加上
watch com.xxx.bizcenter.pay.api.rest.PaymentActionApiController payCodePay -x 2 -n 1

2.4.2  观察当前对象中的属性

watch 也可以看某个对象的属性,比如你的配置类里的参数配置的是生产环境的参数还是测试环境的参数等,但你要记住 watch 是方法监控,你要执行到那个类的那个方法的时候才能看,下边会说一个不执行某个方法,可以直接看的命令:

# 查看 YouyunPayAction  类里的 authChange 变量值
# target  target就表示 YouyunPayAction 对象
# target.authChange 表示只取对象的 authChange 属性
watch com.xxx.bizcenter.pay.domain.pay.payAction.YouyunPayAction pay 'target.authChange' -x 4 -n 1

2.5  trace

trace 命令能主动搜索 class-patternmethod-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路,(详细可以看该命令官方文档以及参数说明哈)这个比较常用:

# 比如查看 PayChannelAction  类的 payCodePayAsync 方法
# -n 1 表示执行 1 次
trace com.xxx.bizcenter.pay.domain.pay.PayChannelAction payCodePayAsync -n 1

是不是就一眼就能看出哪个方法耗时了。

2.6  vmtool

vmtool 利用JVMTI接口,实现查询内存对象,强制 GC 等功能,(详细可以看该命令官方文档以及参数说明哈)这个也比较常用:

2.6.1  获取某个类下的实例对象

# 比如获取 YouyunPayAction 的实例
# --limit 10 表示取10个 记得一定带limit 别傻乎乎的有的不会用的 取个 String类 不带 limit 我疯了
vmtool --action getInstances --className com.xxx.bizcenter.pay.domain.pay.payAction.YouyunPayAction --limit 10

2.6.2  指定返回结果展开层数

# 比如我要看 TicketValidTimeHandle 类实例下的属性
# -x 2 表示展开的参数层深 默认是1
vmtool --action getInstances --className com.xxx.bizcenter.pay.job.TicketValidTimeHandle --limit 10 -x 2

2.6.3  执行表达式

# 比如上面的我只想看 TicketValidTimeHandle 的 noEffect 属性:
# --express 表达式
vmtool --action getInstances --className com.xxx.bizcenter.pay.job.TicketValidTimeHandle --limit 10 --express 'instance[0].noEffect'

3  小结

好啦,最近常用的就这些,有理解不对的地方欢迎指正哈。

posted @ 2024-05-18 13:46  酷酷-  阅读(181)  评论(0编辑  收藏  举报