Java诊断工具 | Arthas

Java诊断工具 | Arthas

1. Arthas是什么

Arthas官网
Arthas 是Alibaba开源的Java诊断工具

2. Arthas可以解决的问题

2-1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?

  • 使用sc className -d 可以查看类的详细信息,包括类路径
  • 使用trace ClassName functionName可以查看方法的调用链,可以看到其中调用方法抛出的Exception

2-2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?

  • 使用sc newClassName查看新添加的类是否存在
  • 使用sm className.newFunction -d查看新添加的方法是否存在
  • 使用jad classname 反向编译出java文件,查看新添加的改动是否存在

2-3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?

  • 使用watch ClassName functionName '{loader,clazz,method,target,params,returnObj,throwExp}' 'condition' 可以查看方法的调用详情,包括方法的调用者信息,入参,返回值,异常,运行时间等.
  • 使用tt -t ClassName functionName -n 5可以记录并显示方法的前五次调用信息,而且可以通过tt -i index_no -p的方式重现方法调用.

2-4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!

2-5. 是否有一个全局视角来查看系统的运行状况?

  • dashboard可以提供一个系统的实时数据面板

2-6. 有什么办法可以监控到JVM的实时运行状态?

  • jvm可以查看jvm的运行数据

2-7. 怎么快速定位应用的热点,生成火焰图?

  • 启动profilerprofiler start
  • 获取已采集的sample的数量profiler getSamples
  • 查看profiler状态profiler status
  • 停止profilerprofiler stop,这时会输出火焰图的位置,打开即可查看

3. Arthas的安装和使用

下载arthas-boot.jar,然后用java -jar的方式启动:

curl -O https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar

4. jvm相关命令

4-1. dashboard当前系统的实时数据面板,ctrl + c中断

dashboard
dashboard

4-2. thread 查看jvm线程堆栈信息,thread -b可以查看死锁

  • thread 显示所有线程的概览
  • thread id显示指定线程ID的堆栈信息
  • thread -n 3查看当前最忙的前三个线程
  • thread -b找出现在阻塞其他线程的线程
  • thread -i 5000指定采样间隔,这个是采集5秒内的数据.会在5秒后返回统计信息
  • thread -state WAITING指定显示某种状态的线程

4-3. jvm 查看jvm整体概览,可以查看运行时间

  • jvm显示jvm的数据汇总,具体内容分为以下几块
    • runtime 包括jvm开始时间,启动参数,class_path等
    • class-loading 已加载类的数量,总共加载类数量,已卸载类的数量
    • garbage-collectors 显示使用的垃圾收集器及垃圾收集次数
    • memory 堆内存空间使用情况
    • thread 线程总数,守护线程数,死锁数量

4-4. sysprop 查看系统的属性

4-5. sysenv 查看jvm的环境变量,包括jvm运行的main方法类

4-6. getstatic查看类的静态属性

4-7. ognl调用静态方法

  • ognl '@java.lang.System@out.println("hello")'会在程序的控制台输出hello

5. class/classloader相关

5-1. sc 查看jvm已加载的类的信息search class,支持*号匹配

  • 可用参数
    • -d 列出类的详细信息,包括类名,类所在的位置,类的ClassLoader
    • -f 需要与-d同时使用,显示类的成员变量

5-2. sm 查看类的方法信息search method

  • 可用参数
    • -d展示详细方法描述(方法所在类,方法名,修饰符,入参,返回值)

5-3. jad [className] 反编译Class

5-4. mc 内存编绎器memory compile,把.java文件编译为.class文件

  • mc /temp/Test.java
  • 可通过-c指定类加载器mc -c 327a647b /tmp/Test.java
  • 可通过-d指定输出目录mc -d /tmp/output tmp/ClassA.java tmp.ClassB.java
  • 可以配合redefine命令实现热更新代码

5-5. redefine加载外部的.class文件,redefine jvm已加载的类

  • redefine /tmp/Test.class
  • redefine -c 327a647b /tmp/Test.class /tmp/Test$Inner.class
  • redefine的限制
    • 不允许新增field和method
    • 正在跑的函数,没有退出不能生效,因为没退出的话,一直在栈中,代码无法重新加载,其他方法能够出栈重新再入栈后就是已经修改后的代码了.

5-6. dump dump已加载类的byte code到特定目录

  • dump java.lang.String 将String的class文件dump到指定位置,会显示具体位置在哪里

5-7. classloader查看所有加载的类信息,classloader信息

  • classloader 展示出所有已加载的类
  • classloader -l 展示每个classloader加载了多少类
  • classloader -t 展示类加载器的继承树

6. monitor/watch/trace相关

6-1. monitor 方法执行监控

  • monitor className functionName监控className.functionName被调用的情况,默认120秒统计一次,可以使用-c 5设置5秒统计一次
  • 统计信息包括时间戳,类名,方法名,这段时间内方法被调用的总次数,调用成功的次数,失败的次数,平均执行时间,失败率

6-2. watch 方法执行数据观测,包括入参,返回值,异常等

  • watch的参数说明
    • class-pattern 类名表达式匹配
    • method-pattern 方法名的表达式匹配
    • express 观察表达式,ognl的格式
      • 可观察的内容有:
        • lader:本次调用类所在的ClassLoader
        • clazz:调用方法在哪个类中申明的
        • method:显示方法在哪个类中被调用的
        • target:本次调用类的实例
        • params:本次调用参数列表,可使用下标获取某个位置的参数params[0],如果参数为空则是个空数组
        • returnObj:本次调用返回对象,方法正常返回的值,如果无返回值,则为null
        • throwExp:本次调用抛出的异常,被捕获处理后的异常不算
        • isThrow:是否抛出异常
        • isReturn:是否正常返回
        • isBefore
    • condition-express 条件表达式
    • -b 在方法调用之前观察
    • -e 在方法异常之后观察
    • -s 在方法返回之后观察
    • -f 在方法结束之后观察,默认是这个
    • -x 指定输出结果属性的遍历深度,默认为1
  • 示例:
    • 查看方法的参数和返回值:watch com.MyClass myTest '{params,returnObj}'
    • 按照条件过滤:watch com.MyClass myTest '{params,target}' 'params[0]<0'
    • 按照调用耗时(ms)过滤:watch com.MyClass myTest '{params}' '#cost>200'

6-3. trace 方法内部调用路径,并输出方法路径上的每个节点上耗时

  • trace com.MyClas myFun
  • trace com.MyClass myFun '#cost > 10'根据调用耗时过滤

6-4. stack 输出当前方法被调用的调用路径

  • 查看某个方法是从哪里被执行的.

6-5. tt 方法执行时数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同时间下的调用进行观测

  • tt -t MyClass myFun -n 3记录下myFun的下三次调用信息,如果myFun有多个重载,它们的调用都被算入进来了,可以使用过滤条件过滤下.
  • tt -t MyClass myFun 'params.length==1' 'params[0] instanceof Integer' 'isThrow'记录myFun的调用信息,其中参数只有一个Integer类型的,且只有抛出异常了才记录
  • tt -l 查看保存下来的调用信息
  • tt -s 'method.name==myFun'筛选方法名为myFun的记录
  • tt -i 1000 查看指定index为1000的调用详情,其中1000是记录的编号
  • tt -i 1000 -p重新调用一次index为1000的这个方法
    • 注意,重新调用的时候ThreadLocal信息丢失
    • tt保存的只是当时环境对象的引用,如果方法中改变了对象的内容,tt就无法看到当时最准确的值

7. 后台异步任务

8. web console

原文地址:https://www.cnblogs.com/Serenity1994/p/12495303.html