认识

Arthas是阿里巴巴开源的Java诊断工具,基本使用场景是定位复现一些测试环境和生产环境比较难以定位问题。可以在线排查问题,以及动态追踪Java代码,实时监控JVM状态等等。
过去定位问题的手段
开发阶段:没有太多限制,直接使用IDE调试,debug,随意重启
测试和生产阶段:一般不允许重启

  1. 抓包,项目简单的时候在浏览器或者app上看报文,项目复杂、涉及很多rpc调用的时候需要在服务器上抓包。
  2. 看日志,异常和重点业务打印日志到文件中,想要添加日志定位问题,就需要重新发布代码,流程复杂而且影响很大。
  3. 分析工具,如jstat、jmap、jstack、 jconsole、visualvm、Java Mission Control、MAT等

Arthas能干什么?
1、是否有一个全局视角来查看系统的运行状况?
2、有什么办法可以监控到 JVM 的实时运行状态?
3、为什么 CPU 又升高了,到底是哪里占用了 CPU ?
4、运行的多线程有死锁吗?有阻塞吗?
5、程序运行耗时很长,是哪里耗时比较长呢?如何监测呢?
6、这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
7、我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
8、遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
9、线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现?

原理简介

Arthas使用java编写,启动后attach到Jvm,实现watch、trace等命令

  1. Instrument和Attach API
    Jdk5增加了一个包java.lang.instrument,提供了对Jvm底层组件的访问能力,Instrument要求在运行前利用命令行参数或者系统参数设置代理类,VM启动完成之后(绝大多数类加载前)初始化。
    Jdk6以后,针对这点进行了改进,开发者可以在main函数执行之后再启动自己的Instrument应用,入口是agentmain函数。arthas就是通过这个实现的。
  2. ASM
    ASM是一个Java字节码操作框架,用来动态生成class或者增强class,cglib的底层就是它,arthas也是通过它实现对class的增强的。
    Arthas增强功能的核心是Enhancer和AdviceWeaver这两个类,对方法进行Aop织入,达到watch,trace等效果。

安装和启动

安装:方式有多种

  1. 直接下载一个可以启动的jar包然后用java -jar的方式启动
  2. 用官方提供的as.sh脚本一键安装
  3. 用rpm的方式安装
    一般使用第1种就行,只要把jar包放到服务器上就可以使用了,也是官方比较推荐的方式

启动:
直接使用java –jar arthas-boot.jar进行启动,启动后会列出所有java进程,选择需要诊断的目标进程就行。启动的时候至少要一个java程序在跑,不然会自动退出。

退出:
退出当前连接用quit或者exit命令
完成退出arthas用stop命令

浏览器访问
有的时候我们希望在另一台电脑上访问,arthas支持远程连接其他机器。
启动的时候添加–target-ip参数指定IP,因为默认启动的时候只监听127.0.0.1
比如:java -jar arthas-boot.jar --target-ip 10.10.10.10

http接口访问
提供http RESTful的形式进行调用,请求和响应均为 JSON 格式的数据。
请求格式为POST http://ip:8563/api
请求参数有:
action : 请求的动作/行为。
requestId : 可选请求 ID,由客户端生成。
sessionId : Arthas 会话 ID,一次性命令不需要设置会话 ID。
consumerId : Arthas 消费者 ID,用于多人共享会话。
command : Arthas command line 。
execTimeout : 命令同步执行的超时时间(ms),默认为 30000。
举个例子:返回繁忙线程
{
“action”: “exec”,
“requestId”: “123456”,
“command”: “thread -n 5”
}

使用

jvm相关

dashboard,系统实时数据面板,可以看到线程、内存、系统信息,可以设置刷新间隔
dashboard –i 1000 表示每一秒刷新一次

jvm,当前jvm信息
memory,当前jvm内存信息
sysenv,查看jvm环境变量
sysprop,查看jvm的系统属性

sc和sm

sc,搜索jvm中的类信息

  1. 查看加载了哪些类
    sc com.xxx.*
  2. 查看一个类的具体信息
    sc –d com.xxx.xxx
  3. 查看类中有哪些变量
    sc -d –f com.xxx.xxx

sm,搜索jvm中的方法信息

  1. 查看加载了哪些方法
    sm com.xxx
  2. 方法的具体信息
    sm –d com.xxx.xx

thread

thread,查看线程信息和堆栈

  1. 查看当前所有线程
    thread –all
  2. 查看最繁忙几个线程及其堆栈
    thread –n 3
  3. 查看指定线程的堆栈信息
    thread id
  4. 查看阻塞其他线程的线程
    thread -b

logger

logger命令,用来查看和控制日志级别

  1. 查看所有logger信息
    logger
    2.查看指定包的logger信息
    logger –n com.xxx
  2. 修改日志级别
    logger --name ROOT --level debug
  3. 修改指定包的日志级别
    logger –n com.xxx --level debug

heapdump

heapdump:导出dump文件(进程的内存镜像),可以配合jvisualvm、mat等分析工具使用
使用案例:

  1. heapdump arthas-output/dump.hprof
  2. 下载该hprof文件,在浏览器或者arthas-output目录下
  3. 使用jvisualvm分析内存

反编译

jad,用于反编译代码并查看

  1. 编译整个类
    jad com.xxx
  2. 编译某方法
    jad com.xxx getUser
    3.其他参数, --source-only仅打印源码, --lineNumber设置显示或者不显示行号
    jad --source-only --lineNumber false com.xxx

dump,将已加载类的bytecode dump到指定目录中
dump com.xxx
将dump下的class文件拖到IDEA中可以看到反编译的结果

retransform

retransform,加载外部class文件,替换jvm中已加载的类
使用案例:

  1. 反编译jad com.xxx xxxmethod查看结果
  2. 添加定位日志,编译新的class文件,使用retransform ./xxx.class装载进jvm
  3. 再次反编译查看结果,已经替换为新的class文件
  4. 使用结束后retransform –l查看已替换类,retransform –d id,取消替换

方法监控

monitor,监控一个方法在一段时间内的调用次数、平均响应时长、成功率等
monitor com.xxx getXxx -c 5 其中-c用来设置监控时长,默认120s

stack,监控方法被调用的路径
stack com.xxx getXxx –n 3 其中-n用来设置被调用次数

trace,监控方法调用的其他方法以及耗时

  1. 捕捉三次方法调用
    trace com.xxx getXxx –n 3
  2. 包含jdk调用,默认仅展示非jdk方法
    trace --skipJDKMethod false com.xxx getXxx –n 3
  3. 过滤耗时大于3s的方法
    trace --skipJDKMethod false com.xxx getXxx ‘#cost > 3000’

watch,观测方法执行的数据,包括入参、返回值、异常
使用watch需要用到观察表达式,比如“{params,returnObj}”表示需要展示参数和返回值

  1. 默认观察表达式为“{params, target, returnObj}”,-x表示遍历层级,如果不写的话将只有一层,实际使用至少要设置2层
    watch com.xxx getXxx –x 3
  2. 自定义观察表达式,打印异常
    watch com.xxx getXxx –x 3 "{params,returnObj,throwExp}“

tt,和watch功能类似,但是更高级

火焰图

profiler,查看应用的热点,Windows系统不支持
profiler start
profiler status
profiler stop --format html
生成html文件后打开,纵向为堆栈深度,横向宽度代表cpu热点

技巧

案例:
检查死锁,thread –b
cpu占用高,thread –n 5 查看最繁忙的线程
接口响应慢但是不知道具体是哪个方法慢,trace
查看已发布代码是否是自己修改过的,jad
想要查看方法调用的入参出参,watch

技巧:涉及输入类和方法时,输入命令后先输类和方法,再输其他参数,这样类和方法才能用tab快速输入
比如输入watch –x 2后,后面的类和方法都需要一个字一个字输入;输入watch后直接输入com.xx就可以用tab提示,类和方法都输完后在输入-x 2,整句命令的效果是一样的。