Arthas
简单
记录下命令:
https://www.cnblogs.com/theRhyme/p/10659265.html
java -jar arthas-boot.jar
进入arthas实例信息。
dashboard
查看当前系统的实时数据面板
sc
sc -d *MathGame
通过sc命令来查找JVM里已加载的类
jad
jad demo.MathGame
jad java.lang.String
通过jad命令来反编译代码
watch
watch demo.MathGame primeFactors returnObj
通过watch命令可以查看函数的参数/返回值/异常信息
sysprop
可以打印所有的System Properties信息
并且可以通过grep来过滤 sysprop | grep user
jvm
jvm命令会打印出JVM的各种详细信息
vmoption
vmoption PrintGCDetails :查看特定的选项
查看,更新VM诊断相关的参数
history
可以查看所有的历史命令。
getstatic
getstatic demo.MathGame random: 显示demo.MathGame类中的静态属性random
通过getstatic命令可以方便查看类的静态属性
thread
thread -b : 查看死锁的状态
thread -i 1000 -n 3: 指定采样时间,每过1000毫秒采样,显示最占时间的3个线程
thread --state WAITING : 查看所有等待的线程
查看所有的线程 可以通过thread + id查看线程
redefine
加载外部的.class 文件,redefine到JVM里
注意,readfine后的原来的类不能恢复,redefine有可能失败(比如增加了新的field)
reset命令对redefine的类无效。如果想重置,需要readfine原始的字节码
redefine命令和jad/watch/trace/monitor/tt 等命令会冲突。执行完redefine之后,如果再执行上面提到的命令,则会把redefine的字节码重置。
redefine的限制
- 不允许新增加到field/method
- 正在跑的函数,没有退出不能生效。
结合jad/mc 命令使用
步骤:
- 使用jad反编译demo.MathGame输出到/root/MathGame.java
jad --source-only demo.MathGame > /root/MathGame.java
- 按上面的代码编辑完毕之后,使用mc内存中对新的代码编译
mc /root/.MathGame.java -d ./root
- 使用redefine命令加载新的字节码
redefine /root/demo/MathGame.class
history
显示所有敲过的命令
class/classloader相关命令
sc
可以查找所有JVM已经加载到的类。如果搜索的是接口,还会搜索所有的实现类。比如查看所有的Filter实现类:
参数说明
sc javax.servlet.Filter
通过-d参数,可以打印出类的加载信息,很方便查找类加载问题
sc -d javax.servlet.Filter
sc支持通配,比如搜索所有的StringUtils:
sc *StringUtils
sm
查看已加载类的方法信息
"Search-Method"的简写,这个命令能搜索出所有已经加载了Class信息的方法信息。
sm 命令只能看到由当前类所声明(declaring)的方法,父类则无法看到。
参数说明
sm java.math.RoundingMode
通过-d参数可以打印函数的具体属性:
sm -d java.math.RoundingMode
也可以查找特定的函数,比如查找构造函数:
sm java.math.RoundingMode <init>
ognl语法
http://commons.apache.org/proper/commons-ognl/language-guide.html
Arthas快捷键
输入keymap可以查看
进阶
dump
将已加载类的字节码文件保存到特定目录:logs/arthas/classdump
参数
- 把String类的字节码文件保存到 ~/logs/arthas/classdump/目录下
dump java.lang.String
- 把demo包下所有的类的字节码文件保存到 ~/logs/arthas/classdump/目录下
dump demo.*
**作用:**正在虚拟机中运行的程序的字节码文件提取出来,保存到相应的目录下
不同的类加载器放在不同的目录下
classloader
获取类加载器的信息
作用
- classloader 命令将JVM中所有的classloader的信息统计出来,并可以展示继承树,urls等。
- 可以让指定的classloader去getResources,打印出来所有查找的resouces的url。对于ResourcesNotFoundException异常比较有用。
参数说明
举例
- 默认按类加载器的类型查看统计信息
classloader
- 按类加载器的实例查看统计信息,可以看到类加载器的hashcode
classloader -l
- 查看classloader的继承树
classloader -t
主要作用
- 显示所有类加载的信息
- 获取某个类加载器所在的jar包
- 获取某个资源在哪个jar包中
- 加载某个类
monitor
monitor : 监控指定类中的执行情况
作用:
- 对匹配 class-pattern / method-pattern的类,方法的调用进行监控
- monitor命令是一个非实时返回命令,实时返回命令是输入之后立即生效
- 而非实时返回的命令,则是不断的等待目标进程返回信息,直到用户输入Ctrl + C 为止
参数说明
方法拥有一个命名参数[c : ] ,意思是统计周期(cycle of output),拥有一个整形的参数值
举例
过5秒监控一次,类demo.MathGame中primeFactors方法
monitor -c 5 demo.MathGame primeFactors
监控项 | 说明 |
---|---|
timestamp | 时间戳 |
class | Java类 |
method | 方法(构造方法,普通方法) |
total | 调用次数 |
success | 成功次数 |
fail | 失败次数 |
rt | 平均耗时 |
小结
monitor命令的作用是什么?
用来监视一个时间段中指定方法的执行次数,成功次数,失败次数,耗时等信息。
watch
观察到指定方法的调用情况
作用
方法执行数据观测,让你能方便的观察到指定方法的调用情况
能观察到的范围为:返回值,抛出异常,入参,通过编写OGNL表达式进行对应变量的查看
参数说明
watch的参数比较多,主要因为它能在4个不同的场景观察对象
这里重点要说明的是观察表达式,观察表达式的构成主要由ognl表达式组成,所以你可以这样写"{params,returnObj}",只要是一个合法的ognl表达式,都能被正常支持
特别说明
- watch命令定义了4个观察点事件点,即
-b
方法异常后,-s
方法返回后,-f
方法结束后 - 4个观察事件点,
-b
,-e
,-s
默认关闭,-f
默认打开,当指定观察点被打开后,在相应事件点会对观察表达式进行求值并输出 - 这里要注意方法入参和方法出参的区别,有可能在中间被修改导致前后不一致,除了
-b
事件点params
代表方法入参外,其余事件都代表方法出参 - 当使用
-b
时,由于观察事件点是在方法调用前,此时返回值或异常均不存在
举例
观察demo.MathGame类中primeFactors方法出参和返回值,结果属性遍历深度为2
params表示所有参数数组(因为不确定是几个参数),returnObject表示返回值
watch demo.MathGame primeFactors “{params,returnObj}” -x 2
观察方法入参,对比前一个例子,返回值为空(事件点为方法执行前,因此获取不到返回值)
watch demo.MathGame primeFactors “{params,returnObj}” -x 2 -b
观察当前对象中的属性,如果想查看方法运行前后,当前对象中的属性,可以使用target关键字,代表当前对象
watch demo.MathGame primeFactors ‘target’ -x 2
使用target.field_name访问当前对象的某个属性
watch demo.MathGame primeFactors ‘target.illegalArgumentCount’
同时观察方法调用前和方法返回后,参数里-n 2,表示只执行两次
这里输出结果中,第一次输出的是方法调用的观察表达式的结果,第二次输出的是方法返回后的表达式结果
params表示参数,target表示执行方法的对象,returnObject表示返回值
watch demo.MathGame primeFactors “{params,target,returnObj}” -x 2 -b -s -n 2
例子: 监听传入参数小于0的情况
watch demo.MathGame primeFactors “{params[0] , target}” “params[0]<0”
小结
参数名称 | 参数说明 |
---|---|
[s] | begin监视方法执行前的情况 |
[e] | exception监视出现异常的情况 |
[s] | success执行成功的情况 |
[f] | finsh执行完毕的情况,包含成功或失败 |
trace
目标
方法内部调用路径,并输出方法路径的每个节点耗时
作用
trace
命令能主动搜索class-pattern / method-pattern
对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路
观察表达式的构成主要由ognl表达式组成,所以你可以这样写"{params,returnObj}"
, 只要是一个合法的ognl表达式,都能被正常支持
很多时候我们只想看到某个方法rt大于某个时间之后的trace结果,现在Arthas可以按照方法执行的耗时来进行过滤了,例如trace *StringUtils isBlank '#cost>1000'
表示当执行时间超过100ms的时候,才会输出trace的结果。
watch/stack/trace 这三个命令都支持#cost
耗时条件过滤
参数说明
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式,使用OGNL表达式 |
[E] | 开启正则表达式匹配,默认是通配符匹配 |
[n:] | 设置命令执行次数 |
#cost | 方法执行耗时,单位是毫秒 |
举例
如果方法调用的次数很多,那么可以用-n参数指定捕获结果的次数。比如下面的例子里,捕捉到一次调用就退出的命令。
trace demo.MathGame run -n 1
默认情况下,trace不会包含jdk里的函数调用,如果希望trace jdk里的函数,需要显示设置 --skipJDKMethod false。
trace --skipJDKMethod false demo.MathGame run
据调用耗时过滤,trace大于0.5ms的调用路径
trace demo.MathGame run ‘#cost > .5’
可以用正则表匹配路径上的多个类和函数,一定程度上达到多层trace的效果
trace -E com.test.ClassA | org.test.ClassB method1 | method2 | method3
小结
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式 |
#cost | 过滤条件,只追踪满足条件的耗时方法 |
stack
作用
输出当前方法被调用的调用路径
介绍
很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本不知道这个方法是从哪里被执行了,此时你需要的是stack命令。
参数说明
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式,OGNL |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[n: ] | 执行次数限制 |
举例
获取primeFactors的调用路径
stack demo.MathGame primeFactors
条件表达式来过滤,第0个参数的值小于0,-n表示获取2次
stack demo.MathGame primeFactors ‘params[0] < 0’ -n 2
据执行时间来过滤,耗时大于0.5毫秒
stack demo.MathGame primeFactors ‘#cost>0.5’
tt
作用
记录下指定方法每次调用的入参和返回信息,并能对这些不同时间下调用的信息进行观测
介绍
watch 虽然很方便和灵活,但需要提前想清楚观察表达式的拼写,这对排查问题而言要求太高,因为很多时候我们并不清楚问题出自何方,只能靠蛛丝马迹进行擦测
这个时候如果能记录下当时方法调用的所有入参和返回值,抛出的异常会对整个问题的思考与判断非常有帮助。
于是乎,TimeTunnel命令就诞生了
参数解析
tt的参数 | 说明 |
---|---|
-t | 记录某个方法在一个时间段中的调用 |
-l | 显示所有已经记录的列表 |
-n 次数 | 只记录多少次 |
-s 表达式 | 搜索表达式 |
-i 索引号 | 查看指定索引号的详细调用信息 |
-p | 重新调用指定的索引号时间碎片 |
表格字段说明
表格字段 | 字段解释 |
---|---|
INDEX | 时间片段记录编号,每一个编号代表着一次调用,后续tt还有很多命令都是基于此编号指定记录操作,非常重要 |
TIMESTAMP | 方法执行的本机时间,记录了这个时间片段所发生的本机时间 |
COST(ms) | 方法执行的耗时 |
IS-RET | 方法是否以正常返回的形式结束 |
IS-EXP | 方法是否以抛异常的形式结束 |
OBJECT | 执行对象的hashCode() ,注意,曾经有人误认为是对象在JVM中的内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体 |
CLASS | 执行的类名 |
METHOD | 执行的方法名 |
小结
作用:记录指定方法每次调用的入参和返回值,并后期还可以对这些信息进行观测
tt的参数 | 说明 |
---|---|
-t | 记录方法在一个时间段中调用 |
-l | 显示所有已经记录的列表 |
-n 次数 | 只记录多少次 |
-s 搜索表达式 | 指定搜索表达式 |
-i 索引号 | 查看它的详细信息 |
profile火焰图
命令
profiler | 命令作用 |
---|---|
profile start | 启动profiler,默认情况下,生成cpu的火焰图 |
profiler list | 显示所有支持的事件 |
profiler getSamples | 获取已采集的sample的数量 |
profiler status | 查看profiler的状态,运行时间 |
profiler stop | 停止profiler,生成火焰图的结果,指定输出目录和输出格式: svg/html |