Arthas 日常记录

3,688 阅读5分钟

首先分享之前的所有文章 , 欢迎点赞收藏转发三连下次一定 >>>> 😜😜😜
文章合集 : 🎁 juejin.cn/post/694164…
Github : 👉 github.com/black-ant
CASE 备份 : 👉 gitee.com/antblack/ca…

一 . 前言

Arthas 是一个 Java 诊断程序 , Arthas 官方 已经很详细的描述了命令的使用 , 如果想整体学习可以查看.

而这一篇文档记录了从最开始接触到 Arthas 到逐步深入过程中的一些记录和感悟 , 整理成文档以便处理.

使用场景

  • 如果是一个可以复现的线上问题,而代码中又无法看出为什么会出现这样的问题
  • 如果你先追踪线上的实际运行情况,在线上 debug 代码逻辑
  • 如果你想直接介入线上代码的运行,并且对线上代码进行热更新

二. 入门使用

// 官方文档 @ https://arthas.aliyun.com/doc/quick-start.html

// Step 1 :下载官方 JAR 
wget https://arthas.aliyun.com/arthas-boot.jar

// Step 2 : 启动 arthas
java -jar arthas-boot.jar
    
// Step 3 : 选择对应的Java 进程 (PS : 启动后会显示所有的进程)

// Step 4 : 输入 dashboard , 查看当前进程信息
    
// 补充 : 其他主要的参数
- 通过thread命令来获取到MainClass : thread 1 | grep 'main('
- 通过 jad 反编译 : jad demo.MathGame
- 通过watch命令来查看返回值 : watch demo.MathGame primeFactors returnObj    
    

三. 命令整理

image.png

image.png

四. 问题梳理

4.1 ClassLoader 在其中的作用

在很多命令中都涉及到 classLoader , 我们可以通过 classLoader 先获取到 hash 码 ,再查询具体的参数

// 查看 classLoader 
classloader -l

// 在查看对象的时候通过 classLoader 获取对象
getstatic -c 3d4eac69 ClassName methodName
mc -c 327a647b /tmp/Test.java >> 通过 ClassLoader 加载


总结

Arthas 的初始操作不多 ,更多的应该是基于实际问题的处理,后续文章会陆续往这个方向思考。

附录:常见使用方式

n.1 展示当前系统实时运行情况

通过运行 dashboard 命令即可查看当前系统的运行情况 , 有如下核心参数 :

image.png

n.2 Thread 进程获取函数信息

// 显示最忙的3个线程
> thread -n 2

// 显示当前运行的线程
> thread
> thread all

// 显示指定线程ID的线程
> thread 543

// 指定时间间隔
> thread -n 3 -i 1000

// 查看指定状态的线程 
> thread --state WAITING

// 查找当前阻塞的线程
thread -b

n.3 jad 反编译代码

// 反编译指定类路径 
> jad com.mythymeleaf.demo.config.MyWebMvcConfig

// 反编译只生成源码
> jad --source-only demo.MathGame

// 反编译指定方法
> jad demo.MathGame main

n.4 JVM 查看

- LOADED-CLASS-COUNT : 加载的class数目
- COUNT: JVM 当前活跃的线程数
- DAEMON-COUNT: JVM 当前活跃的守护线程数
- PEAK-COUNT: 从 JVM 启动开始曾经活着的最大线程数
- STARTED-COUNT: 从 JVM 启动开始总共启动过的线程次数
- DEADLOCK-COUNT: JVM 当前死锁的线程数
- MAX-FILE-DESCRIPTOR-COUNT:JVM 进程最大可以打开的文件描述符数
- OPEN-FILE-DESCRIPTOR-COUNT:JVM 当前打开的文件描述符数

n.5 查看 JVM 已加载的类

SC 查看 JVM 中已经加载的类

// 模糊查找加载的类型 
sc demo.*

// 显示类的详细信息
sc -d com.mythymeleaf.demo.controller.DemoController

// 输出类的成员变量信息
sc -d -f com.mythymeleaf.demo.controller.DemoController

SM 查询类的方法信息

// 查询类中的方法
sm java.lang.String

// 查看方法的详细信息
sm -d java.lang.String toString

getstatic 获取类的静态信息

getstatic ClassName method

ognl 查看变量的值

ognl 就需要深度说说了 ,ognl 是一种强大的表达式语言 , 该语言最重要的是支持对对象方法的调用,同时支持类静态的方法调用和值访问 , ognl 的调用主要分为以下几类 :

  • 直接调用静态函数 : 写法就是 @类@方法 ,同时可以把参数传进去
  • 查看静态字段 : 同样 @类@字段名
  • 集合操作 :
  • 赋值操作 : 以 #value1=? 格式 , 创建对象等

@ cloud.tencent.com/developer/a…

// ognl 原生语法
@java.lang.String@format('foo %s', 'bar')

// 调用静态函数 (调用后会直接在服务上执行)
ognl '@java.lang.System@out.println("hello")'
ognl '@java.lang.Math@max(10, 20)'

// 获取静态字段
ognl '@demo.MathGame@random'

// 普通对象调用
ognl '#obj.method( 参数 )'

// 赋值操作 
ognl '#value="abv"'
ognl '#value1="abc", #value2="efg", {#value1, #value2}'

// 对象创建
ognl 'new java.lang.String("hello world")'
ognl '(#user=new User(),  #user.name="一灰灰Blog", #user.age=18, #user)'

// 集合操作
ognl '"name" in {"name", "hello"}' >> 判断是否包含

n.6 方法执行情况监控 - Watch

Watch 的 表达式常量 :

- clazz : 对象的类
- method : 构造函数或方法
- params : 方法的参数数组
- params[0..n] : 参数数组的元素
- returnObj : method的返回对象
- throwExp : 方法的抛出异常
- isReturn : 返回结束的方法
- isThrow : 方法以引发异常结束

Watch 常用的语句

// 查看方法的执行情况 (会打印6次方法的调用)
watch com.test.points.clean.impl.UserServices processData -n 6

// 打印指定输入参数的方法
watch com.test.points.clean.impl.UserServices processData 'params[0]=="Arthas"'
watch com.test.points.clean.impl.UserServices processData 'params[0].size==2'
watch com.test.points.clean.impl.UserServices processData 'params[1].username="antBlack"'

// 指定打印参数
watch com.test.points.clean.impl.UserServices processData {params,returnObj}
watch com.test.points.clean.impl.UserServices processData {clazz,returnObj}
watch com.test.points.clean.impl.UserServices processData {method,returnObj}

// 指定对象的遍历深度 (参数可能只会打一个引用 , 则需要通过遍历深度进行更深度的打印)
watch com.test.points.clean.impl.UserServices processData {params,returnObj} -x 2

// 查看返回异常的请求方法
watch com.test.points.clean.impl.UserServices processData throwExp 'params[0].size==2'

n.6 方法调用监控 - Monitor

Monitor 是一种维度的监控 ,主要监控调用次数 , 成功次数 ,失败次数等

image.png

// 统计方法的调用情况
monitor com.test.points.clean.impl.UserServices processData -c 5

// 通过参数获取监控
monitor -c 5 com.test.points.clean.impl.UserServices processData "params[0] <= 2"

n.7 查看方法的调用路径 Trace

image.png

// 打印方法执行时间
trace com.test.points.clean.impl.UserServices processData 

// 跳过 JDK 方法

// 只打印调用时间超过 10 秒的方法
trace com.test.points.clean.impl.UserServices processData '#cost > 10'

// 打印多个类路径
trace -E com.test.ClassA|org.test.ClassB method1|method2|method3

// 跳过 JDK 方法
trace --skipJDKMethod false com.test.points.clean.impl.UserServices processData -n 2

n.8 查看方法调用时空隧道 tt

// 查看调用情况 @ https://arthas.aliyun.com/doc/tt.html#%E8%AE%B0%E5%BD%95%E8%B0%83%E7%94%A8
tt -t com.gang.web.demo.controller.BeanController testUser
(PS : 这个调用可以实时记录)

// 通过表达式进行筛选
tt -s 'method.name=="search"'

// 有服务端重调 (通过索引ID)
tt -i 1004 -p

image.png