一、常用命令
注:arthas官网 本文基于3.7.2版本,本文采用官网demo
#下载并启动demo进程
curl -O https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar > /dev/null 2>&1 &
#下载并运行arthas追踪上述进程
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
1.1 watch
主要用于查看调用过程中的相关数据
- 命令格式
watch class-pattern method-pattern express [condition-express]
class-pattern: 要观察的类的表达式,一般指定具体的类即全路径
method-pattern: 方法名,一般指定具体的方法
express: 需要观察的表达式(基于当前根对象的ognl表达式)
condition-express: 过滤表达式(基于当前根对象的ognl表达式)
注意:
- watch为实时命令
express
和condition-express
都是基于当前观察时的同一个OgnlContext- params如果有变化,
-b
和-f
是不一样的- 观察结果location的值有:
AtEnter
,AtExit
,AtExceptionExit
,函数入口,正常 return,抛出异常- 如果没有
condition-express
,默认为true
- 命令选项
-b
: 表示在方法执行前观察
-e
: 表示在方法抛出异常时观察
-s
: 表示在方法正常执行完成时观察
-f
: 表示在方法执行结束后观察,包含正常结束和异常,默认开启
-x
: 针对观察的express
的对象最大嵌套对象的深度(a.b.c),默认为1最大为4
-n
: 表示观察多少次,默认会一直观察,可以设置如-n 5
观察5次后不再观察
-v
: 会打印Condition express
的具体值和判断结果,用来区分没有请求和未匹配上
- 常用场景:
#常见观察{params,returnObj,throwExp},ognl语法,表示这3个属性组合list集合
watch demo.MathGame primeFactors {params,returnObj,throwExp}
#仅观察入参
watch demo.MathGame primeFactors params
#只在异常时观察
watch demo.MathGame primeFactors {params,returnObj,throwExp} -e
#针对某个入参过滤
watch demo.MathGame primeFactors {params,throwExp} 'params[0] > 100'
#根据入参过滤
watch demo.MathGame primeFactors 'params[0]' 'params[0] > 10' -b
#获取target的属性
watch demo.MathGame primeFactors 'target.illegalArgumentCount'
#访问的静态属性
ognl '@demo.MathGame@random.nextInt(10)'
#调用target的方法
watch demo.MathGame primeFactors 'target.print(1,{1,2,3})'
#同时在观察方法调用前和调用后
watch demo.MathGame primeFactors -b -f -n 5 -x 3
#基于执行时长过滤调用
watch demo.MathGame primeFactors {params,returnObj} '#cost > 1' -n 5 -x 3
#打印condition的执行情况,如果没有condtion,默认为true
watch demo.MathGame primeFactors {params,returnObj} '#cost > 1' -n 5 -x 3 -v
1.2 monitor
周期性监测调用过程,分析调用时长、成功率等
- 命令格式
monitor class-pattern method-pattern [condition-express]
class-pattern: 要观察的类的表达式,一般指定具体的类即全路径
method-pattern: 方法名,一般指定具体的方法
condition-express: 过滤表达式(基于当前根对象的ognl表达式)
注意:
- monitor为非实时命令
condition-express
基于当前观察时的OgnlContext- 如果没有
condition-express
,默认为true
- 命令选项
-b
: 在方法调用之前计算 condition-express,因为params方法执行后可能有变化
-n
: 监测多少个周期,默认100
-c
: 单个周期那监测多少次方法执行
- 常用场景:
#只对满足条件的调用监测
demo.MathGame primeFactors "params[0] <= 2"
#只对满足条件的调用监测,且是满足调用前的入参条件
demo.MathGame primeFactors "params[0] <= 2"
1.3 tt
用于记录调用过程,并用于后续分析
1.追踪调用记录
- 命令格式
#记录指定方法的执行情况
tt -t class-pattern method-pattern [condition-express]
class-pattern: 要观察的类的表达式,一般指定具体的类即全路径
method-pattern: 方法名,一般指定具体的方法
condition-express: 过滤表达式(基于当前根对象的ognl表达式)
注意:
condition-express
都是基于当前观察时的OgnlContext- 如果没有
condition-express
,默认为true- 会同时把ognlContext保存下来,供后续查询
- 命令选项
-n
: 记录请求次数,超出后不再记录
-v
: 会打印Condition express
的具体值和判断结果,params是调用前的参数
2.检索/查看调用记录
#查看所有保存的调用记录
tt -l
#按条件搜索保存的调用记录,也是基于Advice对应的OgnlContex对象,表达式可以是多个条件的and
tt -s search-express
- 使用场景
#搜索异常调用的记录
tt -s 'isThrow'
#搜索正常调用技术的记录
tt -s 'isReturn'
#按调用的方法名搜索
tt -s 'method.name=="primeFactors"'
#按调用方法名和执行时长搜索
tt -s 'method.name=="primeFactors" and #params[0] > 1'
#查看指定调用记录
tt -i 1001
3.回放调用
#查看指定
tt -i 1001 -p
- 命令选项
--replay-times
: 指定回放调用次数
--replay-interval
: 指定回放调用间隔,默认1000(ms)
4.观察保存好的调用记录
#查看指定调用记录的相关上下文,也是基于当时的OgnlContext,
tt -w [watch-expression] -i INDEX
- 命令选项
-x
: 指定观察对象的遍历深度,和watch时是一致的(#cost取不到)
- 常见使用场景
#查看调用记录的入参、出参、异常
tt -w '{params,returnObj,throwExp}' -i 1000 -x 3
5.使用tt的注意点
- ThreadLocal之类的变量追踪不到
- tt的OgnlContext快照中是各参数的引用,有可能回放时已经发生变化
1.4 trace
用于查看调用栈及耗时
- 命令格式
monitor class-pattern method-pattern [condition-express]
class-pattern: 要观察的类的表达式,一般指定具体的类即全路径
method-pattern: 方法名,一般指定具体的方法
condition-express: 过滤表达式(基于当前根对象的ognl表达式)
注意:
- trace为实时命令
condition-express
基于当前观察时的OgnlContextcondition-express
中的params是方法执行结束后的params- 如果没有
condition-express
,默认为true
- 命令选项
-n
: 追踪多少次调用
-v
:显示condition-express
的值和判断结果,params是调用后的参数
- 常用场景:
#根据参数过滤
trace demo.MathGame primeFactors 'params[0] > 0' -v -n 5
#根据调用时长过滤
trace demo.MathGame primeFactors '#cost > 1' -v -n 5
1.5 stack
用于查看调用栈
- 命令格式
stack class-pattern method-pattern express [condition-express]
class-pattern: 要观察的类的表达式,一般指定具体的类即全路径
method-pattern: 方法名,一般指定具体的方法
condition-express: 过滤表达式(基于当前根对象的ognl表达式)
注意:
- stack为实时命令
condition-express
都是基于当前观察时的同一个OgnlContext- 如果没有
condition-express
,默认为true,params为方法执行后的params
- 命令选项
-n
: 表示观察多少次,默认会一直观察,可以设置如-n 5
观察5次后不再观察
-v
: 会打印Condition express
的具体值和判断结果,用来区分没有请求和未匹配上
- 常用场景:
#根据参数过滤
stack demo.MathGame primeFactors 'params[0] > 0' -v -n 5
#根据调用时长过滤
stack demo.MathGame primeFactors '#cost >= 1' -v -n 5
1.6 ognl
用于调用指定方法或查看对象,相当于Ognl.getValue方法
ognl express
express: 执行的ognl表达式(基于当前根对象的ognl表达式)
- 命令选项
-x
: 获取对象时的遍历深度
- 常用场景:
#执行静态方法或静态字段
ognl '@java.lang.System@out.println("hello")'
#执行多个ognl表达式,并将结果输出(多命令执行时Ognl的语法)
ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
二、其他
2.1 Ognl表达式理解
参考:Ognl总结
2.2 OgnlContext根对象
根对象的类型是com.taobao.arthas.core.advisor.Advice
根对象的所有属性: {loader,clazz,method,target,params,returnObj,throwExp,isBefore,isThrow,isReturn}
该OgnlContext对象适用的命令有:watch
,monitor
,stack
,tt
,trace
2.3 常见过滤表达式
常用场景总结
#根据参数个数区分重载方法
'params.length==1'
#根据指定参数类型区分重载方法
'params[1] instanceof Integer'
#根据入参指定条件
'params[0] > 1'
'parmas[2].equals("17611112222") and params[3] > 1'
'parmas[0].size() > 1'
'params[0].contains(2047800010054508L)'
'parmas[0].isEmpty()'
'parmas[0] != null'
#根据执行时间
'#cost > 10'
#将集合map转换成另一个集合,再判断是否包含某个值
'returnObj != null and returnObj.{getId()}.contains(2047800010054508L)'
2.4 获取springbean或调用bean
思路是先获得ApplicationContext,再调用ApplicationContext.getBean
思路1:拦截ApplicationAware的bean方法调用
思路2: 直接调用有注入ApplicationContext的静态类
思路3: 直接用vmtool获取对应bean的class实例
tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()'
三、其他命令
vmtool
常用场景: 用内存中获取某class的实例,获取结果数组会绑定到instances
变量上。
-x n
表示展示的层次, 和普通命令使用一样
--limit n
表示最多获取实例数组的数量
--classLoaderClass loaderClassName
指定classLoader
-c classLoaderHashCode
指定classLoader的hashCode来指定classLoader(sc
获得)
--express instances的调用ognl表达式
获取实例后进行方法调用或获取相关信息
注: 指定classLoader是非必选的。如果是单例的也可不指定
#根据class获取对应实例数组并绑定到`instances`变量上,它是数组。`instances`可以在express里直接使用
# 获取ApplicationContext实例
vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext
# 获取ApplicationContext实例后进行方法调用
vmtool --action getInstances -c 19469ea2 --className org.springframework.context.ApplicationContext --express 'instances[0].getBeanDefinitionNames()'
# 直接获取单实例
vmtool --action getInstances --className com.xxx.GxCmccOperatorService --express 'instances[0].isp()'
不常用场景:
vmtool --action forceGc #强制GC
vmtool --action interruptThread -t 1 #interrupt 指定线程, threadId可以使用thread命令获取。
sc
search class的简写
常用场景: 查找内存中指定Class的加载信息
-d
输出当前类的详细信息
-f
输出当前类的所有成员变量定义信息(需要配合参数-d 一起使用)
sc -d demo.MathGame #打印指定类的详细信息
sc -d -f demo.MathGame #打印出类的 Field 信息
sysenv
查看JVM 的环境属性
sysenv #查看所有环境变量
sysenv keyName #查看单个环境变量
sysprop
查看或修改当前 JVM 的系统属性
sysprop #查看所有属性
sysprop java.version #查看单个属性
sysprop user.country CN #设置或修改单个属性
quit/exit/logout/q/reset/stop/session
arthas环境信息相关
quit/exit/logout/q #退出当前Arthas客户端,其他Arthas客户端不受影响。等同于exit、logout、q三个指令
reset classPattern #将被Arthas增强过的类还原,stop时会重置所有增强过的类. 不带参数还原所有
stop #关闭Arthas服务端,所有Arthas客户端全部退出. 同时会重置掉所有做过的增强类
session #查看当前会话的信息,显示当前绑定的java进程的pid 以及会话 id
thread
线程相关的命令
thread #当没有参数时,显示第一页线程的信息.默认按照 CPU 增量时间降序排列
thread -n 3 #展示当前最忙的前 N 个线程
thread threadId #显示指定线程的运行堆栈. id为thread命令后的第一列ID的值
thread -b #找出当前阻塞其他线程的线程
thread -i 1000 #指定采样时间间隔,单位ms
thread -n 3 -i 1000 #列出 1000ms 内最忙的 3 个线程栈
thread --state WAITING #查看指定状态的线程
logger
查看/更新logger信息
logger #查看所有 logger 信息
logger -n org.springframework.web #查看指定名字的 logger 信息
logger -c 2a139a55 #查看指定classloader的logger信息,hashcode是变化的,需要先查看当前ClassLoader信息
logger --classLoaderClass sun.misc.Launcher$AppClassLoader#执行classLoader
logger --name ROOT --level debug #更新 logger level
修改某个类或包的日志级别(最常用)
sc -d demo.MathGame #获取该类加载器的hash码,用于logger命令-c的选项值
logger -c 0x1385 --name demo.MathGame --level debug #更新 logger level
classloader
加载器相关信息
classloader #将 JVM 中所有的 classloader 的信息统计出来.并可以展示继承树,urls 等
classloader -l #类加载实例查看统计信息. (包括hash值)
classloader -t #按ClassLoader的继承树展示
classloader -c 3d3fcdb0 #查看ClassLoader实际加载的urls
classloader -c 3d3fcdb0 -r META-INF/MANIFEST.MF #使用ClassLoader去查找resource,验证是否存在
classloader -c 3d3fcdb0 -r java/lang/String.class #使用ClassLoader查找class文件,验证加载的jar
classloader -c 3d4eac69 --load java.lang.String #使用ClassLoader去加载类r
dump
dump 已加载类的 bytecode 到特定目录
dump java.lang.String #指定class,默认会加载到用户目录下
dump demo.* #classPattern适配
dump -d /tmp/output java.lang.String #指定输出目录
dump -c 3d4eac69 demo.* #指定classLoader