Bootstrap

Arthas常用命令之trace、watch、jad、mc

目录

一、Arthas是什么

二、Arthas能解决哪些问题

三、Arthas安装启动

3.1 环境说明

 3.2 下载地址

3.3 快速使用

四、Arthas基础命令

五、Arthas查看jvm相关数据

六、Arthas搬砖过程中的常用命令

6.0  查看已加载的类信息

6.1  查看已加载类中的方法信息

6.2 反编译指定已加载类的源码

6.3 监视一个时间段中指定方法的执行次数,成功次数,失败次数

6.4 输出当前方法被调用的调用路径链

6.5 输出方法路径上的每个节点上耗时, 定位因 RT 高导致的性能问题

6.7 观察:返回值、抛出异常、入参,通过编写OGNL 表达式进行对应变量的查看

七、生产环境运行了java程序,在线调试实战

一、Arthas是什么

        阿里开源的Java诊断工具,它可以在运行时对Java应用程序进行动态诊断和调试

二、Arthas能解决哪些问题

  • 当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决

    • 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
    • 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
    • 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
    • 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
    • 是否有一个全局视角来查看系统的运行状况?
    • 有什么办法可以监控到 JVM 的实时运行状态?

三、Arthas安装启动

3.1 环境说明

Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,
也支持浏览器直接访问对应的ip+端口,固定端口 8563
默认情况下,arthas 只 listen 127.0.0.1,所以如果想从远程连接,使用 --target-ip参数指定 listen 的 IP

 3.2 下载地址

github:https://github.com/alibaba/arthas
官网:https://arthas.aliyun.com/
版本:Arthas-3.6.7

3.3 快速使用

 

启动 :java -jar arthas-boot.jar
命令执行后会展示进程列表,输入数字编号进入对应的进程

运行日志路径:/root/logs/arthas/arthas.log

退出 arthas

 如果只是退出当前的连接,其他客户端不受影响,可以用 quit或者exit命令
目标进程上的 arthas 还会继续运行,端口保持开放,下次连接时执行java -jar arthas-boot.jar可以直接连接上
如果想完全退出 arthas,可以执行stop命令

四、Arthas基础命令

version - 输出当前目标 Java 进程所加载的 Arthas 版本号

base64 - base64 编码转换,和 linux 里的 base64 命令类似

cat - 打印文件内容,和 linux 里的 cat 命令类似

cls - 清空当前屏幕区域

echo - 打印参数,和 linux 里的 echo 命令类似

grep - 匹配查找,和 linux 里的 grep 命令类似

help - 查看命令帮助信息

history - 打印命令历史

keymap - Arthas 快捷键列表及自定义快捷键

pwd - 返回当前的工作目录,和 linux 命令类似

quit - 退出当前 Arthas 客户端,其他 Arthas 客户端不受影响

reset - 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类

session - 查看当前会话的信息

stop - 关闭 Arthas 服务端,所有 Arthas 客户端全部退出

tee - 复制标准输入到标准输出和指定的文件,和 linux 里的 tee 命令类似

五、Arthas查看jvm相关数据

jvm 相关

  • dashboard - 当前系统的实时数据面板
  • heapdump - dump java heap, 类似 jmap 命令的 heap dump 功能
  • jvm - 查看当前 JVM 的信息
  • memory - 查看 JVM 的内存信息
  • ognl - 执行 ognl 表达式
  • perfcounter - 查看当前 JVM 的 Perf Counter 信息
  • sysenv - 查看 JVM 的环境变量
  • sysprop - 查看和修改 JVM 的系统属性
  • thread - 查看当前 JVM 的线程堆栈信息
  • vmoption - 查看和修改 JVM 里诊断相关的 option

 命令案例操作: dashboard

 列详解:

字段说明
idJava 级别的线程 ID
name线程名称
group线程组名称
proirity线程优先级,1 ~ 10 之间的数字,越大优先级越高
state线程的状态
cpu线程的 cpu 使用率
delta_time上次采样之后线程运行增量 CPU 时间,数据格式为秒
time线程运行总 CPU 时间,数据格式为 分:秒
interupted当前线程是否中断
daemon是否是 daemon 守护线程
字段说明
used当前使用了多少内存
total总共分配了多少内存
max最大使用了多少
usage使用比例
gc垃圾回收器

 命令案例操作:thread

thread - 查看当前 JVM 的线程堆栈信息

  • --all :显示所有匹配的线程,默认就是第一页线程信息

  • -i:设置cpu统计时的采样间隔,单位为毫秒 thread -i 2000

  • [ id ]:查看指定ID的线程堆栈 thread 54

  • -n :查看CPU使用率最高的TopN个线程, 如果值为-1表示显示所有线程 thread -n 3

  • -b :展示阻塞线程 thread -b

  • --state : 根据线程状态筛选线程 thread --state TIMED_WAITING

    • 状态类型:NEW, RUNNABLE, TIMED_WAITING, WAITING, BLOCKED,TERMINATED

六、Arthas搬砖过程中的常用命令

6.0  查看已加载的类信息

  sc -d  -f net.wnn.archwebproject.ProductController    #  -d 详情,-f 类属性输出

6.1  查看已加载类中的方法信息

sm -d net.wnn.archwebproject.ProductController 

6.2 反编译指定已加载类的源码

jad - 反编译指定已加载类的源码

  • 反编译整个类 jad net.wnn.archwebproject.ProductController

  • 通过--source-only选项,可以只打印源代码

  • 应用场景

    • 查看某个类的业务逻辑,方法逻辑
    • 查看本地修改的代码是否线上成功生效

反编译类的某个方法 jad net.wnn.archwebproject.ProductController query

6.3 监视一个时间段中指定方法的执行次数,成功次数,失败次数

  • monitor - 方法执行监控

    • 非实时响应,需要对应的方法有被调用才行,所以需要触发web接口请求
    • 监视一个时间段中指定方法的执行次数,成功次数,失败次数,耗时等这些信息
    • monitor -c 2 net.xdclass.archwebproject.ProductController query

触发web接口请求:

timestamp:方法执行时间戳

class : 方法执行所属类

method:执行的方法名称

total:执行次数   success:成功次数 fail:失败次数 avg-rt:执行耗时(毫秒)  fail-rate:失败百分比

6.4 输出当前方法被调用的调用路径链

stack - 输出当前方法被调用的调用路径, 一个方法被执行的路径非常多,不知道这个方法是从那里被执行,就可以使用

stack net.wnn.archwebproject.ProductController test2

6.5 输出方法路径上的每个节点上耗时, 定位因 RT 高导致的性能问题

trace - 方法内部调用,输出方法路径上的每个节点上耗时, 定位因 RT 高导致的性能问题,每次只能跟踪一级方法的调用链路

  ts: 时间戳,表示日志记录的时间,该字段的值为2023年8月03日上午10点48分44秒。

  • thread_name: 线程名称,表示当前执行该日志记录的线程名称,该字段的值为http-nio-8080-exec-10。
  • id: 线程ID,表示当前执行该日志记录的线程ID,该字段的值为20。
  • is_daemon: 是否为守护线程,该字段的值为true,表示该线程是守护线程。
  • priority: 线程优先级,该字段的值为5,表示该线程的优先级为5。
  • TCCL: 线程上下文类加载器,表示当前线程的上下文类加载器为TomcatEmbeddedWebappClassLoader。

拓展一:

默认情况下,trace不会包含jdk里的函数调用,如果希望trace jdk里的函数, 需要显式设置--skipJDKMethod false

trace --skipJDKMethod false  net.wnn.archwebproject.ProductController find

拓展二:

根据调用耗时,过滤大于10ms的调用路径

trace net.wnn.archwebproject.ProductController find '#cost >10'

6.7 观察:返回值抛出异常入参,通过编写OGNL 表达式进行对应变量的查看

watch - 方法执行数据观测, 观察:返回值抛出异常入参,通过编写OGNL 表达式进行对应变量的查看

  • 应用场景:查看方法调用栈,参数入参,返回值等调试
  • 默认的 观察表达式,默认值是{params, target, returnObj}
  • -x 参数表示遍历深度,可以调整来打印具体的参数和结果内容,默认值是 1, 最大是4

watch net.wnn.archwebproject.ProductController * {params,returnObj} -x 4

七、生产环境运行了java程序,在线调试实战

背景:

生产环境运行了java程序,需要在线调试

不重启JVM程序,动态调整,打印参数或修改方法内部逻辑

使用到的相关命令:

  • jad 把字节码文件反编译成源代码
  • mc 在内存中把源代码编译成字节码文件
  • redefine 把新生成的字节码文件在内存中执行

命令学习:

mc Memory Compiler/内存编译器,编译.java文件生成.class

# 在内存中编译Hello.java为Hello.class
mc /root/Hello.java

# 可以通过-d命令指定输出目录(输出对应的路径会有package路径)
mc -d /root/test   /root/Hello.java

  • redefine

    • 加载外部的.class文件,redefine到JVM里
    • redefine后的原来的类不能恢复,redefine有可能失败(比如增加了新的field)
    • 不允许新增加field/method
    • 正在跑的函数,没有退出不能生效 比如main

实战操作:修改某个方法的接口返回值,增加多一个参数

步骤一、

#使用jad反编译
 jad --source-only net.wnn.archwebproject.ProductController > /dev1/ProductController.java 

 步骤二、 修改代码

  步骤三、
#使用mc内存中对新的代码编译

mc /dev1/ProductController.java  -d /dev1

 注意,mc 命令有可能失败。如果编译失败可以在本地编译好.class文件,再上传到服务器

 编译四、redefine  /dev1/ProductController.class

然后再请求下路径即可 

 Arthas官网链接:mc | arthas

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;