阿丹:
因为一个图太大,直接放出来影响观看,我给他们分开来。
图中关键标识:
基础命令:
class相关
jvm相关
字节码增强
-
ArtHas
-
基础命令
-
help 查看命令帮助信息
-
cls 清空当前屏幕区域
-
session 查看当前会话的信息
-
reset 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
-
version 输出当前目标 Java 进程所加载的 Arthas 版本号
-
history 打印命令历史
-
quit 退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
-
stop 和shutdown命令一致
-
shutdown 关闭 Arthas 服务端,所有 Arthas 客户端全部退出
-
keymap Arthas快捷键列表及自定义快捷键
-
options 查看或设置Arthas全局开关
-
-
class相关
-
sc
-
作用
-
查看JVM已加载的类信息
-
-
参数
-
参数表
-
-
<class-pattern>
-
类名表达式匹配
-
sc demo.*
-
-
-
-x, --expand <value>
-
展开层次
-
-
-
-E, --regex
-
开启正则表达式
-
sc -E org\\.apache\\.commons\\.lang\\.StringUtils
-
-
-
-d, --details
-
显示详细信息
-
-
-
-f, --field
-
输出当前类的成员变量信息(需要配合参数-d一起使用)
-
sc -d -f demo.MathGame
-
-
-
-
-
sm
-
作用
-
“Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。
-
-
参数
-
参数表
-
-
<class-pattern>
-
类名表达式匹配
-
sm java.lang.String
-
-
-
-E, --regex
-
开启正则表达式
-
sm -Ed org\\.apache\\.commons\\.lang\.StringUtils .*
-
-
-
-d, --details
-
显示详细信息,配合方法名使用
-
sm -d java.lang.String toString
-
-
-
-
-
jad
-
作用
-
反编译指定已加载类的源码
-
-
示例
-
反编绎时只显示源代码
-
jad --source-only demo.MathGame
-
-
反编译指定类
-
jad java.lang.String
-
-
反编译指定的函数
-
jad demo.MathGame main
-
-
反编译时指定ClassLoader
-
jad org.apache.log4j.Logger
-
jad org.apache.log4j.Logger -c 69dcaba4
-
-
-
-
mc
-
作用
-
Memory Compiler/内存编译器,编译.java文件生成.class
-
-
基本不用
-
-
redefine
-
作用
-
加载外部的.class文件,redefine jvm已加载的类
-
-
参数
-
-c
-
ClassLoader的hashcode
-
redefine -c 327a647b /tmp/Test.class /tmp/Test\$Inner.class
-
-
-
-p
-
外部的.class文件的完整路径,支持多个
-
redefine /tmp/Test.class
-
-
-
-
组合用法
-
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
-
mc /tmp/UserController.java -d /tmp
-
redefine /tmp/com/example/demo/arthas/user/UserController.class
-
-
限制
-
不允许新增加field/method
-
正在跑的函数,没有退出不能生效,比如下面新增加的System.out.println,只有run()函数里的会生效
-
-
-
dump
-
作用
-
dump 已加载类的 bytecode 到特定目录
-
-
使用参考
-
dump java.lang.String
-
dump demo.*
-
-
-
classloader
-
作用
-
查看classloader的继承树,urls,类加载信息
-
-
参数
-
-a, --all
-
列出所有ClassLoader加载的类,请谨慎使用
-
-
-c, --classloader <value>
-
ClassLoader的hashcode,查看URLClassLoader实际的urls
-
classloader -c 3d4eac69
-
-
-
-h, --help this help
-
-i, --include-reflection-classloader
-
-l, --list-classloader
-
按类加载实例进行统计
-
classloader -l
-
-
-
--load <value>
-
用ClassLoader去加载指定的类,配合-c
-
classloader -c 3d4eac69 --load demo.MathGame
-
-
-
-r, --resource <value>
-
用ClassLoader去查找resource 配合-c
-
classloader -c 3d4eac69 -r META-INF/MANIFEST.MF
-
classloader -c 1b6d3586 -r java/lang/String.class
-
-
-
-t, --tree
-
打印所有ClassLoader的继承树
-
classloader -t
-
-
-
-
-
-
jvm相关
-
dashboard
-
作用
-
当前系统的实时数据面板
-
-
说明
-
面板
-
-
thread
-
作用
-
查看当前线程信息,查看线程的堆栈
-
-
参数
-
参数表
-
-
-n, --top-n-threads <value>
-
指定最忙的前N个线程并打印堆栈
-
thread -n 5
-
-
-
-i, --sample-interval <value>
-
指定cpu占比统计的采样间隔,单位为毫秒
-
thread -i 2000
-
-
-
-b, --include-blocking-thread
-
找出当前阻塞其他线程的线程
-
stack *StringUtils isBlank '#cost>100'
-
-
-
线程id
-
显示线程信息
-
thread 1
-
-
-
-
-
jvm
-
作用
-
查看当前JVM信息
-
-
Thread相关
-
COUNT: JVM当前活跃的线程数
-
DAEMON-COUNT: JVM当前活跃的守护线程数
-
PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数
-
STARTED-COUNT: 从JVM启动开始总共启动过的线程次数
-
DEADLOCK-COUNT: JVM当前死锁的线程数
-
-
文件描述符相关
-
MAX-FILE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符数
-
OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数
-
-
-
sysprop
-
作用
-
查看当前JVM的系统属性(System Property)
-
-
参数
-
参数表
-
-
查看所有
-
sysprop
-
-
<property-name>
-
查看单个属性,支持补全
-
sysprop java.version
-
-
-
<property-value>
-
修改单个属性
-
sysprop user.country CN
-
-
-
-
-
sysenv
-
作用
-
查看当前JVM的环境属性(System Environment Variables)
-
-
参数
-
参数表
-
-
查看所有
-
sysenv
-
-
<env-name>
-
查看单个环境变量
-
sysenv USER
-
-
-
-
-
vmoption
-
作用
-
查看,更新VM诊断相关的参数
-
-
使用
-
查看所有的option
-
vmoption
-
-
查看指定的option
-
vmoption PrintGCDetails
-
-
更新指定的option
-
vmoption PrintGCDetails true
-
-
-
-
logger
-
作用
-
查看logger信息,更新logger level
-
-
使用
-
查看logger配置信息
-
logger
-
-
查看指定名字的logger信息
-
logger -n org.springframework.web
-
-
查看指定classloader的logger信息
-
logger -c 2a139a55
-
-
更新logger level
-
logger --name ROOT --level debug
-
-
查看没有appender的logger的信息
-
logger --include-no-appender
-
-
-
-
getstatic
-
用例
-
getstatic com.alibaba.arthas.Test n 'entrySet().iterator.{? #this.key.name()=="STOP"}'
-
-
作用
-
访问静态变量
-
-
推荐直接使用ognl命令,更加灵活。
-
-
ognl
-
作用
-
执行ognl表达式
-
-
参数
-
指定类加载器
-
-c classloader
-
-
指定展开级别
-
-x extend
-
-
-
使用示例
-
调用静态属性
-
ognl '@全路径类目@静态属性名'
-
ognl '@com.shirc.arthasexample.ognl.OgnlTest@static_str'
-
-
-
调用静态方法
-
ognl '@全路径类目@静态方法名("参数")'
-
简单入参 返回普通对象
-
ognl '@com.shirc.arthasexample.ognl.OgnlTest@getPerson("src",18)' -X 1
-
-
简单入参 返回对象中包含对象和List
-
ognl '@com.shirc.arthasexample.ognl.OgnlTest@getPerson("src",18,2)' -x 1
-
-
方法A的返回值当做方法B的入参
-
ognl '#value1=@com.shirc.arthasexample.ognl.OgnlTest@getPerson("src",18), #value2=@com.shirc.arthasexample.ognl.OgnlTest@setPerson(#value1) ,{#value1,#value2}' -x 2
-
-
执行多行表达式,赋值给临时变量,返回一个List:
-
ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
-
-
方法入参是简单类型列表
-
ognl '@com.shirc.arthasexample.ognl.OgnlTest@getChilds({"jinjidelaomanong","jjdlmn"})' -x 2
-
-
方法入参是一个复杂对象
-
ognl '#obj=new com.shirc.arthasexample.ognl.Shirc("jjdlmn",true),@com.shirc.arthasexample.ognl.OgnlTest@inputObj(#obj)' -x 2
-
-
方法入参是一个Map对象
-
ognl '#inputmap=#{ "foo" : "foo value", "bar" : "bar value" }, @com.shirc.arthasexample.ognl.OgnlTest@getMap(#inputmap)' -x 2
-
-
-
-
读取不同类型的值
-
访问复杂对象属性
-
ognl '@com.shirc.arthasexample.ognl.OgnlTest@getPerson("src",18).name' -x 4
-
-
访问List或者数组类型
-
ognl '@com.shirc.arthasexample.ognl.OgnlTest@getChilds({"jinjidelaomanong","jjdlmn"})[0]' -x 2
-
-
访问Map对象
-
ognl '@com.shirc.arthasexample.ognl.OgnlTest@getMap()["shirc"]' -x 2
-
ognl '@com.shirc.arthasexample.ognl.OgnlTest@getMap()["shirc"].sex' -x 2
-
-
-
-
高级操作
-
投影(Across)
-
在投影中调用方法
-
watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{#this.convert()}'
-
-
简单示例
-
watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{#this.username}' -b -x 2
-
-
在观察表达式里过滤
-
watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{? #this.id > 8}' -b -x 2
-
-
过滤后计数
-
watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{? #this.username.endsWith("9")}.size()'
-
-
子表达式计算
-
watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].size().(#this>5? 20+#this:10+#this)'
-
-
-
-
说明
-
#变量引用 #this 当前对象
-
OGNL的变量方案很简单, 你可以用变量来保存中间结果, 并在后面的代码中再次访问它, 也可以用变量来使整个表达式更加简单易懂. OGNL中的所有变量, 对整个表达式都是全局可见的. 引用变量的方法是在变量名之前加上 # 号
-
OGNL在计算表达式的过程中, 随时会将当前对象保存在 "this"变量中, 这个变量也可以象其他任何变量一样引用,用 #this 表示当前对象
-
-
用例
-
ognl '@com.shirc.arthasexample.ognl.OgnlTest@getMap()["shirc"].(#this.sex=="boy"?"BoyNB":"GirlNB")' -x 2
-
-
-
-
mbean
-
作用
-
这个命令可以便捷的查看或监控 Mbean 的属性信息。
-
-
参数
-
参数表
-
-
<name-pattern>不填该项查看所有
-
名称匹配,详见javax.management.ObjectName
-
mbean org.opendaylight.controller:type=RemoteRp*,name=*
-
-
-
<attribute-pattern>
-
属性匹配,查看mxbean的某个属性
-
mbean org.opendaylight.controller:type=RemoteRp*,name=* Globa*
-
-
-
-n, --number-of-execution <value>
-
刷新属性值的次数
-
-
-
-E, --regex
-
开启正则表达式
-
mbean -E java.lang:type=Threading PeakThreadCount|ThreadCount|DaemonThreadCount
-
-
-
-i, --interval <value>
-
刷新属性值的时间间隔 (ms)
-
mbean -i 1000 org.opendaylight.controller:type=RemoteRp*,name=*
-
-
子主题 6
-
-m, --metadata
-
显示mbean的元数据
-
-
-
-
说明
-
-
heapdump
-
作用
-
dump java heap, 类似jmap命令的heap dump功能
-
-
使用
-
dump到指定文件
-
heapdump /tmp/dump.hprof
-
-
只dump live对象
-
heapdump --live /tmp/dump.hprof
-
-
dump到临时文件
-
heapdump
-
-
-
-
-
字节码增强
-
tt
-
作用
-
方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
-
-
与watch对比
-
watch 虽然很方便和灵活,但需要提前想清楚观察表达式的拼写,这对排查问题而言要求太高,因为很多时候我们并不清楚问题出自于何方,只能靠蛛丝马迹进行猜测。 这个时候如果能记录下当时方法调用的所有入参和返回值、抛出的异常会对整个问题的思考与判断非常有帮助。
-
-
参数
-
<class-pattern> <method-pattern>
-
类名 + 方法名 配合-t使用
-
tt -t *Test print 'params[1] instanceof Integer'
-
-
<condition-express>
-
条件表达式,可以通过条件表达式解决重载问题
-
tt -t demo.MathGame primeFactors 'params.length>=0'
-
-
-t, --time-tunnel
-
记录方法的执行时间碎片
-
-
-d --delete
-
根据index删除,和-i配合使用
-
tt -d -i 1064
-
-
--delete-all
-
删除所有
-
-
-x <value>
-
指定输出结果的属性遍历深度,默认为1
-
-x 3
-
-
-h
-
帮助信息
-
-
-i, --index <value>
-
显示一个时间片段的详细信息
-
tt -i 5
-
-
-n, --limits <value>
-
设置执行次数,不然多次调用的方法可能会内存溢出
-
-
-l, --list
-
展示所有时间片段
-
-
-p, --play
-
重新执行某个时间片段,和-i配合使用
-
tt -i 5 -p
-
-
-E, --regex
-
开启正则表达式匹配,默认为通配符匹配
-
-
--replay-interval <value>
-
执行多次时间间隔,和-p与--replay-interval <value>配合使用
-
-
--replay-times <value>
-
执行多次,和-p配合使用
-
tt -i 1067 -p --replay-interval 1000 --replay-times 3
-
-
-s, --search-express <value>
-
通过OGNL表达式进行查找,支持advice
-
tt -s 'method.name=="primeFactors"'
-
-
-M, --sizeLimit <value>
-
指定结果的字节数组上限,默认10*1024*1024bytes
-
-
-w, --watch-express <value>
-
通过ognl表达式查看time fragments(时间碎片)
-
tt -i 1067 -w params[0]
-
tt -i 1067 -w '{params[0], target, returnObj}'
-
-
-
字段解析
-
注意事项
-
ThreadLocal 信息丢失
-
很多框架偷偷的将一些环境变量信息塞到了发起调用线程的 ThreadLocal 中,由于调用线程发生了变化,这些 ThreadLocal 线程信息无法通过 Arthas 保存,所以这些信息将会丢失。 一些常见的 CASE 比如:鹰眼的 TraceId 等。
-
-
引用的对象
-
需要强调的是,tt 命令是将当前环境的对象引用保存起来,但仅仅也只能保存一个引用而已。如果方法内部对入参进行了变更,或者返回的对象经过了后续的处理,那么在 tt 查看的时候将无法看到当时最准确的值。这也是为什么 watch 命令存在的意义。
-
-
-
-
watch
-
作用
-
让你能方便的观察到指定方法的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。
-
-
参数
-
参数表
-
-
<class-pattern>
-
类名表达式匹配
-
-
-
<method-pattern>
-
你想要观察的方法
-
watch demo.MathGame primeFactors throwExp
-
-
-
<express>
-
观察表达式,你想观察什么 OGNL表达式
-
watch demo.MathGame primeFactors '{params[0], target, returnObj}'
-
-
-
<condition-express>
-
条件表达式,符合条件的观察(boolean)
-
watch demo.MathGame primeFactors params 'params.length>=0'
-
-
-
-b, --before
-
在方法调用之前观察
-
-
-
-s, --success
-
方法成功执行后观察
-
watch demo.MathGame primeFactors "{params,target,returnObj}" -x 2 -b -s -n 2
-
-
-
-e, --exception
-
在方法异常之后观察
-
watch demo.MathGame primeFactors throwExp -e
-
-
-
-f, --finish
-
在方法结束之后观察,包括正常异常场景(默认)
-
-
-
-x, --expand <value>
-
指定输出结果的属性遍历深度,默认为 1
-
-
-
-n, --limits <value>
-
观察的次数
-
-
-
-E, --regex
-
开启正则表达式
-
-
-
-M, --sizeLimit <value>
-
指定结果的字节数组上限,默认10*1024*1024bytes
-
-
-
-
特别说明
-
watch 命令定义了4个观察事件点,即 -b 方法调用前,-e 方法异常后,-s 方法返回后,-f 方法结束后
-
4个观察事件点 -b、-e、-s 默认关闭,-f 默认打开,当指定观察点被打开后,在相应事件点会对观察表达式进行求值并输出
-
这里要注意方法入参和方法出参的区别,有可能在中间被修改导致前后不一致,除了 -b 事件点 params 代表方法入参外,其余事件都代表方法出参
-
当使用 -b 时,由于观察事件点是在方法调用前,此时返回值或异常均不存在
-
-
-
monitor
-
作用
-
方法执行监控
-
对匹配 class-pattern/method-pattern的类、方法的调用进行监控。
-
-
参数
-
参数表
-
-
<class-pattern>
-
类名表达式匹配
-
-
-
<method-pattern>
-
你想要监视的方法
-
monitor org.apache.commons.lang.StringUtils isBlank
-
-
-
-c, --cycle <value>
-
监视周期 默认60s
-
monitor -c 5 demo.MathGame primeFactors
-
-
-
-n, --limits <value>
-
监视几个周期
-
-
-
-E, --regex
-
开启正则表达式
-
-
-
-
说明
-
monitor 命令是一个非实时返回命令
-
-
监控的维度
-
-
stack
-
作用
-
输出当前方法被调用的调用路径
-
-
说明
-
很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。
-
-
参数
-
参数表
-
-
<class-pattern>
-
类名表达式匹配
-
-
-
<method-pattern>
-
你想要监视的方法
-
stack demo.MathGame primeFactors
-
-
-
-n, --limits <value>
-
监视几个周期
-
stack demo.MathGame primeFactors 'params[0]<0' -n 2
-
-
-
-E, --regex
-
开启正则表达式
-
stack -E org\.apache\.commons\.lang\.StringUtils isBlank
-
-
-
<condition-express>
-
条件表达式,支持#cost
-
stack *StringUtils isBlank '#cost>100'
-
-
-
-
-
trace
-
作用
-
方法内部调用路径,并输出方法路径上的每个节点上耗时
-
-
参数
-
参数表
-
-
<class-pattern>
-
类名表达式匹配
-
-
-
<method-pattern>
-
你想要监视的方法
-
trace demo.MathGame run
-
-
-
-j, --jdkMethodSkip
-
跳过jvm方法
-
trace demo.MathGame run -j
-
-
-
-n, --limits <value>
-
监视几个周期
-
-
-
-E, --regex
-
开启正则表达式
-
trace -E com.test.ClassA|org.test.ClassB method1|method2|method3
-
-
-
<condition-express>
-
条件表达式,支持#cost
-
trace *StringUtils isBlank '#cost>100'
-
-
-
-
重要说明
-
很多时候我们只想看到某个方法的rt大于某个时间之后的trace结果,现在Arthas可以按照方法执行的耗时来进行过滤了,例如trace *StringUtils isBlank '#cost>100'表示当执行时间超过100ms的时候,才会输出trace的结果。
-
watch/stack/trace这个三个命令都支持#cost
-
-
注意
-
trace 能方便的帮助你定位和发现因 RT 高而导致的性能问题缺陷,但其每次只能跟踪一级方法的调用链路。
-
trace命令只会trace匹配到的函数里的子调用,并不会向下trace多层。因为trace是代价比较贵的,多层trace可能会导致最终要trace的类和函数非常多。
-
可以用正则表匹配路径上的多个类和函数,一定程度上达到多层trace的效果。
-
trace -E com.test.ClassA|org.test.ClassB method1|method2|method3
-
-
-
-
-