Java虚拟机 动态追踪
时间:2019/3/15 11:59:51
参考:
Java动态追踪技术探究#
Arthas(阿尔萨斯)#
阿里开源的Java诊断工具,采用命令行方式,支持Tab自动补全,相较于JDK提供的 jps
jstack
jinfo
等原生命令更全面更好用。
可以做什么#
- 监控JVM实时运行状况。
- 监控方法的调用耗时。
- 观察方法的返回值、抛出异常、入参等。
- 方法执行记录,需要时可以使用记录的参数等信息多次调用测试。
- 支持
ongl
表达式。 - 支持
Tab
自动补全。 - ...
基础知识#
-
表达式核心变量,。
Arthas
命令参数会使用该类进行一些逻辑判断,比如params.length == 1
method.name="abc"
。参考: 特殊用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
public class Advice { //本次调用类所在的 ClassLoader private final ClassLoader loader; //本次调用类的 Class 引用 private final Class<?> clazz; //本次调用方法反射引用 private final ArthasMethod method; //本次调用类的实例 private final Object target; //本次调用参数列表,这是一个数组,如果方法是无参方法则为空数组 private final Object[] params; //本次调用返回的对象。当且仅当 isReturn==true 成立时候有效,表明方法调用是以正常返回的方式结束。如果当前方法无返回值 void,则值为 null private final Object returnObj; //本次调用抛出的异常。当且仅当 isThrow==true 成立时有效,表明方法调用是以抛出异常的方式结束。 private final Throwable throwExp; //辅助判断标记,当前的通知节点有可能是在方法一开始就通知,此时 isBefore==true 成立,同时 isThrow==false 和 isReturn==false,因为在方法刚开始时,还无法确定方法调用将会如何结束。 private final boolean isBefore; //辅助判断标记,当前的方法调用以抛异常的形式结束。 private final boolean isThrow; //辅助判断标记,当前的方法调用以正常返回的形式结束。 private final boolean isReturn; }
- 常用过滤条件。
'#cost >0'
耗时大于零。
命令#
基础命令#
cls
清空屏幕。help
查看帮助信息。session
查看当前session。reset
重置增强类,重置使用Arthas
过程对类的更改。version
版本号。history
命令历史。quit
退出当前客户端。stop shutdown
关闭Arthas
所有客户端都会退出。keymap
快捷键。
其它命令#
dashboard
查看进程整体运行情况概要界面。thread
查看线程堆栈信息。thread
显示所有线程。thread id
指定线程信息。thread -n number
查看占用率最高的前number
个线程的堆栈信息。thread -b
查看阻塞其它线程的线程。thread -i time
: 线程CPU时间占用时间统计。thread -n 3 -i 1000
指定采样间隔。-
jvm
查看当前JVM信息。 -
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
查看系统属性。 -
sysprop
查看所有属性。 sysprop java.version
查看单个属性。sysprop user.country country
设置属性。sysenv
查看当前JVM的环境属性。vmoption
:查看虚拟机选项配置。vmoption
查看配置。vmoption PrintGCDetails true
设置虚拟机选项配置。logger
: 查看所有logger
信息。logger
查看所有。logger -n org.springframework.web
指定名字查看。mbean
查看 Mbean 的信息。sc
搜索虚拟机已经加载的类信息。sc com.sun.xiaotian.blogger.*
搜索指定包下面的类。sc -d com.sun.xiaotian.blogger.util.PinYin
打印类的详细信息。sc -df com.sun.xiaotian.blogger.model.ArticleInfo
输出类的成员变量。sc -df -x 3 com.sun.xiaotian.blogger.model.ArticleInfo
成员变量深度为3。 10sm
搜索类的方法。sm java.lang.String
搜索指定类的方法。sm -d java.lang.String
搜索指定类的方法,并展示方法的详细信息。sm -d java.lang.String toString
搜索指定类的指定方法。dump
dump已加载的类到特定目录。dump com.sun.xiaotian.blogger.*
dump 指定包。heapdump
dump 堆信息到指定目录。heapdump /tmp/dump.hprof
dump到指定目录。heapdump --live /tmp/dump.hprof
只 dump live 对象。jad
反编译类文件。jad com.sun.xiaotian.blogger.BloggerRun
反编译指定类。jad --source-only com.sun.xiaotian.blogger.BloggerRun
反编译指定类,只显示源码。jad com.sun.xiaotian.blogger.BloggerRun main
反编译指定函数。jad -c @6767c1fc com.sun.xiaotian.blogger.BloggerRun
指定类加载器。classloader
查看classloader的继承树,urls,类加载信息。classloader
类加载器的统计信息。classloader -t
查看类加载器的继承树。classloader -a
查看所有类加载器(危险)。classloader -c 1b6d3586 -r java/lang/String.class
使用类加载器查找类。classloader -c 3d4eac69 --load demo.MathGame
使用类加载器加载类。mc
内存编译器,编译.java
文件。redefine
加载外部class。monitor
监控方法调用。monitor -c 5 demo.MathGame primeFactors
监控方法调用 调用次数、成功次数、失败次数。-c
指定统计周期(单位秒)。watch
观察方法参数、返回值等。-b
方法调用之前-e
方法异常之后-s
方法返回之后-f
方法结束之后(正常返回合异常返回)。watch demo.MathGame primeFactors "{params,returnObj}" -x 2
观察方法出参和返回值,深度为2。watch demo.MathGame primeFactors "{params,returnObj}" -x 2 -b
观察方法入参。watch demo.MathGame primeFactors "{params,target,returnObj}" -x 2 -b -s -n 2
同时观察方法调用前和方法返回后,执行两次。watch demo.MathGame primeFactors "{params,target}" -x 3
调整参数便利深度a.b.c
。watch demo.MathGame primeFactors "{params[0],target}" "params[0]<0"
条件表达式。watch demo.MathGame primeFactors "{params[0],throwExp}" -e -x 2
观察异常信息。watch demo.MathGame primeFactors '{params, returnObj}' '#cost>200' -x 2
按照耗时进行过滤。watch demo.MathGame primeFactors 'target'
观察当前对象中的属性。trace
方法内部调用路径,及每个调用的耗时(方法内部调用)。trace com.sun.xiaotian.blogger.web.FileInfoController getContentByFilePath
查看对应方法里的方法调用及耗时。trace *StringUtils isBlank
通配符。trace -j com.sun.xiaotian.blogger.web.FileInfoController getContentByFilePath
查看对应方法里的方法调用及耗时。过滤掉JDK内部方法。trace demo.MathGame run '#cost > 10'
耗时大于10毫秒。trace -E com.test.ClassA|org.test.ClassB method1|method2|method3
跟踪多个方法。stack
打印方法的调用堆栈,及执行耗时(从哪里调用到方法)。stack demo.MathGame primeFactors
打印方法调用堆栈。stack demo.MathGame primeFactors 'params[0]<0' -n 2
根据参数过滤,限制执行两次。stack demo.MathGame primeFactors '#cost>5'
根据耗时过滤。tt
: TimeTunnel 时空隧道,记录下方法调用时的现场日志(入参、出参、返回值)等,方便后续模拟调用。tt -t com.sun.xiaotian.blogger.web.FileInfoController getContentByFilePath
: 记录方法的调用日志。tt -t -n com.sun.xiaotian.blogger.web.FileInfoController getContentByFilePath
: 记录方法的调用日志 ` 记录三次,方法调用量比较大时使用。、tt -t *Test print params.length==1
方法重载的情况下,只记录参数长度为一的方法执行记录。tt -t *Test print 'params[1] instanceof Integer'
方法重载的情况下,只记录参数类型为指定类型的方法执行记录。tt -t *Test print params[0].mobile=="13989838402"
方法重载的情况下,只记录参数值为指定值的的方法执行记录。tt -l
查看记录的执行日志。tt -s 'method.name=="getContentByFilePath"'
查找指定方法名字的记录。tt -i 1000
查看调用信息,非常详细。-
tt -i 1000 -p
使用记录的日志重新调用一次, 可以指定调用次数、调用间隔等参数。 -
options
设置Arthas
选项,设置属性options json-format true
。 unsafe
是否可以对系统级别的类进行增强,慎重使用,默认false
。dump
是否支持被增强的类dump
到外部文件中。默认false
,如果打开则会 dump 到application-directory/arthas-class-dump
目录。json-format
是否支持 json 序列化输出。默认false
,开启之后回打印实际的返回值。disable-sub-class
是否禁用字类匹配,默认false
默认关闭。打开之后不会匹配字类,缩小匹配范围。batch-re-transform
是否支持对匹配到的类批量进行retransform
操作。默认true
。debug-for-asm
打印 ASM 相关的调试信息,默认false
。save-result
是否开启执行结果存日志功能,默认false
。打开之后所有的命令执行结果都会保存到~/logs/arthas-cache/result.log
中。job-timeout
异步后台任务的默认超时时间。超过时间任务自动停止。时间格式:1d 2h 3m 25s -> 天 小时 分 秒
。pwd
返回当前工作目录。cat
查看文件内容。
部署使用#
Arthas 支持单机版本使用,也支持 server
模式。在单机模式下,需要登录需要监控的机器,然后启动 Arthas
进行使用。在 server
模式下,需要先启动一个 server
服务,然后在需要监控的机器上启动一个 arthas
注册到服务器上,注册成功之后会有一个 代理Id
,然后即可通过Web界面监控注册的机器。
常用命令#
- 查看帮助信息:
java -jar arthas-boot.jar -h
- 简单启动:
java -jar arthas-boot.jar
- 启动 server:
java -jar -Dserver.port=8080 arthas-tunnel-server.jar
,默认 web 端口是8080
, 代理端口是7777
。 - 启动时注册到 server:
java -jar arthas-boot.jar --tunnel-server 'ws://192.168.0.201:7777/ws'
单机版启动: java -jar arthas-boot.jar pid
server 版启动:
- 启动Server:
java -jar -Dserver.port=8080 arthas-tunnel-server.jar
- 注册:
java -jar arthas-boot.jar --tunnel-server 'ws://192.168.0.201:7777/ws
启动成功之后访问: http://ip:8080
,然后输入 代理Id 即可连接。