1.离线安装
下载地址 https://arthas.aliyun.com/download/doc/latest_version?mirror=aliyun
2.启动
2.1 用as.sh启动 解压后 ./as.sh 启动
2.2 用arthas-boot启动 java -jar arthas-boot.jar
3.命令介绍
3.1 sm(search method) 查找方法
usage: sm com.tgram.rwpt.gateway.filter.AccessGatewayFilter
Usage: sm -d com.tgram.rwpt.gateway.filter.AccessGatewayFilter getOrder 展示方法的详细信息
3.2 jad 对类进行反编译
Usage: jad com.tgram.rwpt.gateway.filter.AccessGatewayFilter
3.3 dashboard 当前系统的实时数据面板,按ctrl+c退出
Usage: dashboard -i(刷新数据时间间隔ms) 1000 -n(刷新实时数据的次数) 5
3.4 thread 查看当前线程信息,查看线程的堆栈
Usage: thread -n 3 展示当前最忙的前3个线程的堆栈信息
Usage: thread id 显示指定线程的运行堆栈
Usage: thread -b 找出当前阻塞其他线程的线程(注意, 目前只支持找出synchronized关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持。)
3.5 jvm 查看当前jvm信息
3.6 sysprop 查看当前jvm的系统属性
3.7 sysenv 查看当前jvm的环境属性
3.8 vmoption 查看/更新VM诊断相关参数
3.9 getstatic 查看类的静态属性
Usage: getstatic com.tgram.rwpt.task.entity.ActionEntity COLUMN_TYPE
静态属性可以是复杂对象,通过ognl进行遍历,过滤,访问对象的内部属性等操作
Usage: 假设n是个Map,Map的key是个Enum,我们想过滤出Map中key为某个enum的值
getstatic com.alibaba.arthas.Test n ‘entrySet().iterator.{? #this.key.name==“STOP”}'
3.10 ognl 执行ognl表达式
Usage: ognl ‘@java.lang.System@out.println(“test")' 调用静态函数
Usage: ognl ‘@demo.MathGame@random’ 获取静态类的静态字段
3.11 sc (search class) 查看jvm已加载的类信息
Usage: sc -d -f com.tgram.rwpt.gateway.filter.AccessGatewayFilter -d 输出当前类的详细信息 -f 输出当前 类的成员变量(需要配合参数-d一起使用)
3.12 dump 已加载类的bytecode到特写目录
3.13 watch
watch *.CommonTest test "{params,returnObj,throwExp}" '#cost>10 && params[0]==1' -x 5 -n 1
解析
*.CommonTest 类名
test 方法名
监控入参、返回、异常
params 入参
returnObj 返回
throwExp 异常
监控指标
'#cost>10 && params[0]==1' 耗时超过10ms 且 第一个参数等于1
-x 5 监控数据遍历深度5
-n 1 只监控一次
3.14 tt(TimeTunnel) 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
tt -l 查看调用记录
tt -I index值 查看调用信息
tt -I index值 -p - -replay_times(指定调用次数) - - replay_interval(指定多次调用时间间隔,默认ms) 重做一次调用
进阶
1.案例:排查函数调用异常现象
watch com.example.demo.arthas.user.UserController * '{params,throwExp}’ 'params[0] > 100' -x 2
第一个参数为类名
第二个参数为函数名,支持通配
第三个参数为返回值表达式,它实际上是一个ognl表达式,它支持一些内置对象
-
loader
-
clazz
-
method
-
target
-
params
-
returnObj
-
throwExp
-
isBefore
-
isThrow
-
isReturn
第四个参数为条件表达式
当异常时捕获
watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e
按照耗时进行过滤
watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200’
2.案例 热更新代码, 通过jad/mc/redefine命令实现动态更新代码的功能
2.1 jad反编译UserController,并把编译的结果保存在/tmp/UserController.java中
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
2.2 用vim编辑源文件
Vim /tmp/UserController.java
2.3 sc查找加载UserCotroller的ClassLoader
sc -d *UserController | grep classLoaderHash
2.4使用Mc(Memory Complier)命令来编译,并且通过-c或者—classLoaderClass参数指定ClassLoader
mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
2.4再使用redefine命令重新加载新编译好的UserController.class
redefine /tmp/com/example/demo/arthas/user/UserController.class
案例3 动态更新应用Logger Level
3.1 查找USerController的ClassLoder
sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
3.2用ognl节能logger
ognl —classLoaderClass org.springframework.boot.loader.LaunchedURLClass
3.3单独设置UserController的logger level
ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger.setLevel(@ch.qos.logback.classic.Level@DEBUG)’
4.案例4 获取Spring Context
4.1使用tt命令获取到spring context (tt即TimeTunnel,它可以记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测)
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
4.2 使用tt命令从调用记录里获取 到spring context
tt -i 1000 -w 'target.getApplicationContext()’
4.3 获取spring bean,并调用函数
tt -i 1000 -w 'target.getApplicationContext().getBean("helloWorldService").getHelloMessage()’
案例5 排查http请求返回401
5.1 跟踪所有的Filter函数
trace javax.servlet.Filter *
5.2 通过stack获取调用栈
stack javax.servlet.http.HttpServletResponse sendError 'params[0]==401’
案例6 排查Http请求返回404
6.1跟踪所有servlet函数
trace javax.servlet.Servlet * > /tmp/servlet.txt