跳转至

Java虚拟机 动态追踪

时间:2019/3/15 11:59:51

参考:

  1. Java动态追踪技术探究
  2. Arthas
  3. Arthas文档
  4. Arthas 案例
  5. ONGL
  6. 百度云

Java动态追踪技术探究#

Arthas(阿尔萨斯)#

阿里开源的Java诊断工具,采用命令行方式,支持Tab自动补全,相较于JDK提供的 jps jstack jinfo 等原生命令更全面更好用。

可以做什么#

  • 监控JVM实时运行状况。
  • 监控方法的调用耗时。
  • 观察方法的返回值、抛出异常、入参等。
  • 方法执行记录,需要时可以使用记录的参数等信息多次调用测试。
  • 支持 ongl 表达式。
  • 支持 Tab 自动补全。
  • ...

基础知识#

  1. 表达式核心变量,。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; 
    }
    
    1. 常用过滤条件。
    2. '#cost >0' 耗时大于零。

命令#

基础命令#

  1. cls 清空屏幕。
  2. help 查看帮助信息。
  3. session 查看当前session。
  4. reset 重置增强类,重置使用 Arthas 过程对类的更改。
  5. version 版本号。
  6. history 命令历史。
  7. quit 退出当前客户端。
  8. stop shutdown 关闭 Arthas 所有客户端都会退出。
  9. keymap 快捷键。

其它命令#

  1. dashboard 查看进程整体运行情况概要界面。
  2. thread 查看线程堆栈信息。
  3. thread 显示所有线程。
  4. thread id 指定线程信息。
  5. thread -n number 查看占用率最高的前 number 个线程的堆栈信息。
  6. thread -b 查看阻塞其它线程的线程。
  7. thread -i time: 线程CPU时间占用时间统计。
  8. thread -n 3 -i 1000 指定采样间隔。
  9. jvm 查看当前JVM信息。

  10. COUNT: JVM当前活跃的线程数。

  11. DAEMON-COUNT: JVM当前活跃的守护线程数。
  12. PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数。
  13. STARTED-COUNT: 从JVM启动开始总共启动过的线程次数。
  14. DEADLOCK-COUNT: JVM当前死锁的线程数。
  15. MAX-FILE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符数。
  16. OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数。
  17. sysprop 查看系统属性。

  18. sysprop 查看所有属性。

  19. sysprop java.version 查看单个属性。
  20. sysprop user.country country 设置属性。
  21. sysenv 查看当前JVM的环境属性。
  22. vmoption:查看虚拟机选项配置。
  23. vmoption 查看配置。
  24. vmoption PrintGCDetails true 设置虚拟机选项配置。
  25. logger: 查看所有 logger 信息。
  26. logger 查看所有。
  27. logger -n org.springframework.web 指定名字查看。
  28. mbean 查看 Mbean 的信息。
  29. sc 搜索虚拟机已经加载的类信息。
  30. sc com.sun.xiaotian.blogger.* 搜索指定包下面的类。
  31. sc -d com.sun.xiaotian.blogger.util.PinYin 打印类的详细信息。
  32. sc -df com.sun.xiaotian.blogger.model.ArticleInfo 输出类的成员变量。
  33. sc -df -x 3 com.sun.xiaotian.blogger.model.ArticleInfo 成员变量深度为3。 10 sm 搜索类的方法。
  34. sm java.lang.String 搜索指定类的方法。
  35. sm -d java.lang.String 搜索指定类的方法,并展示方法的详细信息。
  36. sm -d java.lang.String toString 搜索指定类的指定方法。
  37. dump dump已加载的类到特定目录。
  38. dump com.sun.xiaotian.blogger.* dump 指定包。
  39. heapdump dump 堆信息到指定目录。
  40. heapdump /tmp/dump.hprof dump到指定目录。
  41. heapdump --live /tmp/dump.hprof 只 dump live 对象。
  42. jad 反编译类文件。
  43. jad com.sun.xiaotian.blogger.BloggerRun 反编译指定类。
  44. jad --source-only com.sun.xiaotian.blogger.BloggerRun 反编译指定类,只显示源码。
  45. jad com.sun.xiaotian.blogger.BloggerRun main 反编译指定函数。
  46. jad -c @6767c1fc com.sun.xiaotian.blogger.BloggerRun 指定类加载器。
  47. classloader 查看classloader的继承树,urls,类加载信息。
  48. classloader 类加载器的统计信息。
  49. classloader -t 查看类加载器的继承树。
  50. classloader -a 查看所有类加载器(危险)。
  51. classloader -c 1b6d3586 -r java/lang/String.class 使用类加载器查找类。
  52. classloader -c 3d4eac69 --load demo.MathGame 使用类加载器加载类。
  53. mc 内存编译器,编译 .java 文件。
  54. redefine 加载外部class。
  55. monitor 监控方法调用。
  56. monitor -c 5 demo.MathGame primeFactors 监控方法调用 调用次数、成功次数、失败次数。-c 指定统计周期(单位秒)。
  57. watch 观察方法参数、返回值等。 -b 方法调用之前 -e 方法异常之后 -s 方法返回之后 -f 方法结束之后(正常返回合异常返回)。
  58. watch demo.MathGame primeFactors "{params,returnObj}" -x 2 观察方法出参和返回值,深度为2。
  59. watch demo.MathGame primeFactors "{params,returnObj}" -x 2 -b 观察方法入参。
  60. watch demo.MathGame primeFactors "{params,target,returnObj}" -x 2 -b -s -n 2 同时观察方法调用前和方法返回后,执行两次。
  61. watch demo.MathGame primeFactors "{params,target}" -x 3 调整参数便利深度 a.b.c
  62. watch demo.MathGame primeFactors "{params[0],target}" "params[0]<0" 条件表达式。
  63. watch demo.MathGame primeFactors "{params[0],throwExp}" -e -x 2 观察异常信息。
  64. watch demo.MathGame primeFactors '{params, returnObj}' '#cost>200' -x 2 按照耗时进行过滤。
  65. watch demo.MathGame primeFactors 'target' 观察当前对象中的属性。
  66. trace 方法内部调用路径,及每个调用的耗时(方法内部调用)。
  67. trace com.sun.xiaotian.blogger.web.FileInfoController getContentByFilePath 查看对应方法里的方法调用及耗时。
  68. trace *StringUtils isBlank 通配符。
  69. trace -j com.sun.xiaotian.blogger.web.FileInfoController getContentByFilePath 查看对应方法里的方法调用及耗时。过滤掉JDK内部方法。
  70. trace demo.MathGame run '#cost > 10' 耗时大于10毫秒。
  71. trace -E com.test.ClassA|org.test.ClassB method1|method2|method3 跟踪多个方法。
  72. stack 打印方法的调用堆栈,及执行耗时(从哪里调用到方法)。
  73. stack demo.MathGame primeFactors 打印方法调用堆栈。
  74. stack demo.MathGame primeFactors 'params[0]<0' -n 2 根据参数过滤,限制执行两次。
  75. stack demo.MathGame primeFactors '#cost>5' 根据耗时过滤。
  76. tt: TimeTunnel 时空隧道,记录下方法调用时的现场日志(入参、出参、返回值)等,方便后续模拟调用。
  77. tt -t com.sun.xiaotian.blogger.web.FileInfoController getContentByFilePath: 记录方法的调用日志。
  78. tt -t -n com.sun.xiaotian.blogger.web.FileInfoController getContentByFilePath: 记录方法的调用日志 ` 记录三次,方法调用量比较大时使用。、
  79. tt -t *Test print params.length==1 方法重载的情况下,只记录参数长度为一的方法执行记录。
  80. tt -t *Test print 'params[1] instanceof Integer' 方法重载的情况下,只记录参数类型为指定类型的方法执行记录。
  81. tt -t *Test print params[0].mobile=="13989838402" 方法重载的情况下,只记录参数值为指定值的的方法执行记录。
  82. tt -l 查看记录的执行日志。
  83. tt -s 'method.name=="getContentByFilePath"' 查找指定方法名字的记录。
  84. tt -i 1000 查看调用信息,非常详细。
  85. tt -i 1000 -p 使用记录的日志重新调用一次, 可以指定调用次数、调用间隔等参数。

  86. options 设置 Arthas 选项,设置属性 options json-format true

  87. unsafe 是否可以对系统级别的类进行增强,慎重使用,默认 false
  88. dump 是否支持被增强的类 dump 到外部文件中。默认 false,如果打开则会 dump 到 application-directory/arthas-class-dump 目录。
  89. json-format 是否支持 json 序列化输出。默认 false,开启之后回打印实际的返回值。
  90. disable-sub-class 是否禁用字类匹配,默认 false 默认关闭。打开之后不会匹配字类,缩小匹配范围。
  91. batch-re-transform 是否支持对匹配到的类批量进行 retransform 操作。默认 true
  92. debug-for-asm 打印 ASM 相关的调试信息,默认 false
  93. save-result 是否开启执行结果存日志功能,默认 false。打开之后所有的命令执行结果都会保存到 ~/logs/arthas-cache/result.log 中。
  94. job-timeout 异步后台任务的默认超时时间。超过时间任务自动停止。时间格式: 1d 2h 3m 25s -> 天 小时 分 秒
  95. pwd 返回当前工作目录。
  96. 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 即可连接。