arthas:Java 应用问题诊断利器
文章目录
- 一、写在前面
- 二、安装使用
- 1、安装
- 2、测试SpringBoot项目
- 3、卸载
- 三、常用命令
- 1、cls:清除屏幕
- 2、dashboard:统计面板
- 3、dump:下载class文件
- 4、heapdump:堆快照
- 5、jad:反编译
- 6、jvm:查看jvm信息
- 7、logger:日志
- 8、memory:查看内存
- 9、monitor:方法监控
- 10、ognl:执行表达式
- 11、退出客户端:quit、exit、logout、q
- 12、reset、stop:还原、停止客户端
- 13、retransform:加载类
- (1)基本用法
- (2)结合 jad/mc 命令使用
- (3)retransform 的限制
- 14、sysenv:查看jvm环境变量
- 15、sysprop:查看jvm系统属性
- 16、trace:监控方法调用与耗时
- 17、tt:记录方法参数
- 18、vmtool:停止线程、强制GC
- 19、watch:监控函数参数
一、写在前面
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
官方文档:https://arthas.aliyun.com/doc/
Arthas 在生产环境应用时需要谨慎,某些命令比如:trace(深调用链)、heapdump、watch(复杂表达式 / 高频触发),持续字节码修改、大量数据传输,可能导致 CPU 飙升、内存占用增加。
使用时要在业务低峰使用,少用高开销命令(如持续 trace 全链路、频繁 heapdump),Arthas 正常退出reset还原增强过的类,退出时用stop命令
二、安装使用
1、安装
# 下载jar包
curl -O https://arthas.aliyun.com/arthas-boot.jar
# 启动(需要选择一个应用)
java -jar arthas-boot.jar --repo-mirror aliyun --use-http
2、测试SpringBoot项目
(1)启动springboot项目
(2)启动arthas
输入2,回车。
首次会下载arthas,出现下面的命令行之后,就是启动成功了:
3、卸载
# 在 Linux/Unix/Mac 平台
rm -rf ~/.arthas/
rm -rf ~/logs/arthas
Windows 平台直接删除 user home
下面的.arthas和logs/arthas
目录
三、常用命令
1、cls:清除屏幕
非终端模式下使用 cls 指令,会提示"Command ‘cls’ is only support tty session."。
2、dashboard:统计面板
# 参数:[i:] 刷新实时数据的时间间隔 (ms),默认 5000ms
# 参数:[n:] 刷新实时数据的次数
dashboard
数据说明:
ID: Java 级别的线程 ID,注意这个 ID 不能跟 jstack 中的 nativeID 一一对应。
NAME: 线程名
GROUP: 线程组名
PRIORITY: 线程优先级, 1~10 之间的数字,越大表示优先级越高
STATE: 线程的状态
CPU%: 线程的 cpu 使用率。比如采样间隔 1000ms,某个线程的增量 cpu 时间为 100ms,则 cpu 使用率=100/1000=10%
DELTA_TIME: 上次采样之后线程运行增量 CPU 时间,数据格式为秒
TIME: 线程运行总 CPU 时间,数据格式为分:秒
INTERRUPTED: 线程当前的中断位状态
DAEMON: 是否是 daemon 线程
JVM 内部线程
3、dump:下载class文件
#参数名称 参数说明
#class-pattern 类名表达式匹配
#[c:] 类所属 ClassLoader 的 hashcode
#[classLoaderClass:] 指定执行表达式的 ClassLoader 的 class name
#[d:] 设置类文件的目标目录
#[E] 开启正则表达式匹配,默认为通配符匹配# 下载String类到指定目录
$ dump -d /tmp/output java.lang.StringHASHCODE CLASSLOADER LOCATIONnull /tmp/output/java/lang/String.class
Affect(row-cnt:1) cost in 138 ms.# 批量下载class文件
dump demo.*
4、heapdump:堆快照
dump java heap, 类似 jmap 命令的 heap dump 功能。
#dump 到指定文件
[arthas@58205]$ heapdump arthas-output/dump.hprof
Dumping heap to arthas-output/dump.hprof ...
Heap dump file created#只 dump live 对象
[arthas@58205]$ heapdump --live /tmp/dump.hprof
Dumping heap to /tmp/dump.hprof ...
Heap dump file created
5、jad:反编译
#参数名称 参数说明
#class-pattern 类名表达式匹配
#[c:] 类所属 ClassLoader 的 hashcode
#[classLoaderClass:] 指定执行表达式的 ClassLoader 的 class name
#[E] 开启正则表达式匹配,默认为通配符匹配# 示例:反编译String类
jad java.lang.String
# 反编译时只显示源代码
jad --source-only demo.MathGame
# 反编译指定方法
jad demo.MathGame main
# 反编译时不显示行号
jad demo.MathGame main --lineNumber false
# 指定classloader,反编译时如果有多个classloader会提示的
jad org.apache.log4j.Logger -c 69dcaba4
6、jvm:查看jvm信息
jvm
THREAD 相关:
COUNT: JVM 当前活跃的线程数
DAEMON-COUNT: JVM 当前活跃的守护线程数
PEAK-COUNT: 从 JVM 启动开始曾经活着的最大线程数
STARTED-COUNT: 从 JVM 启动开始总共启动过的线程次数
DEADLOCK-COUNT: JVM 当前死锁的线程数
文件描述符相关:
MAX-FILE-DESCRIPTOR-COUNT:JVM 进程最大可以打开的文件描述符数
OPEN-FILE-DESCRIPTOR-COUNT:JVM 当前打开的文件描述符数
7、logger:日志
# 查看logger信息
logger
# 更新 logger level
[arthas@2062]$ logger --name ROOT --level debug
update logger level success.
8、memory:查看内存
$ memory
Memory used total max usage
heap 32M 256M 4096M 0.79%
g1_eden_space 11M 68M -1 16.18%
g1_old_gen 17M 184M 4096M 0.43%
g1_survivor_space 4M 4M -1 100.00%
nonheap 35M 39M -1 89.55%
codeheap_'non-nmethods' 1M 2M 5M 20.53%
metaspace 26M 27M -1 96.88%
codeheap_'profiled_nmethods' 4M 4M 117M 3.57%
compressed_class_space 2M 3M 1024M 0.29%
codeheap_'non-profiled_nmethods' 685K 2496K 120032K 0.57%
mapped 0K 0K - 0.00%
direct 48M 48M - 100.00%
9、monitor:方法监控
监控维度:
监控项 | 说明 |
---|---|
timestamp | 时间戳 |
class | Java 类 |
method | 方法(构造方法、普通方法) |
total | 调用次数 |
success | 成功次数 |
fail | 失败次数 |
rt | 平均 RT |
fail-rate | 失败率 |
#方法拥有一个命名参数 [c:],意思是统计周期(cycle of output),拥有一个整型的参数值#参数名称 参数说明
#class-pattern 类名表达式匹配
#method-pattern 方法名表达式匹配
#condition-express 条件表达式
#[E] 开启正则表达式匹配,默认为通配符匹配
#[c:] 统计周期,默认值为 120 秒
#[b] 在方法调用之前计算 condition-express
#[m <arg>] 指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch <arg>]。# 监控5秒指定方法
monitor -c 5 demo.MathGame primeFactors
# 计算条件表达式过滤统计结果(方法执行完毕之后)
monitor -c 5 demo.MathGame primeFactors "params[0] <= 2"
# 计算条件表达式过滤统计结果(方法执行完毕之前)
monitor -b -c 5 com.test.testes.MathGame primeFactors "params[0] <= 2"
10、ognl:执行表达式
#参数说明
#参数名称 参数说明
#express 执行的表达式
#[c:] 执行表达式的 ClassLoader 的 hashcode,默认值是 SystemClassLoader
#[classLoaderClass:] 指定执行表达式的 ClassLoader 的 class name
#[x] 结果对象的展开层次,默认值 1# 调用静态函数:
ognl '@java.lang.System@out.println("hello")'
# 获取静态类的静态字段:
ognl '@demo.MathGame@random'
11、退出客户端:quit、exit、logout、q
只是退出当前 Arthas 客户端,Arthas 的服务器端并没有关闭,所做的修改也不会被重置。
12、reset、stop:还原、停止客户端
重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端stop时会重置所有增强过的类。
stop关闭 Arthas 服务器之前,会重置掉所有做过的增强类。但是用 redefine 重加载的类内容不会被重置。
# 还原所有修改的类
reset
# 还原指定类
reset Test
13、retransform:加载类
(1)基本用法
retransform /tmp/Test.classretransform -lretransform -d 1 # delete retransform entryretransform --deleteAll # delete all retransform entriesretransform --classPattern demo.* # triger retransform classesretransform -c 327a647b /tmp/Test.class /tmp/Test\$Inner.classretransform --classLoaderClass 'sun.misc.Launcher$AppClassLoader' /tmp/Test.class
(2)结合 jad/mc 命令使用
# jad 命令反编译,然后可以用其它编译器,比如 vim 来修改源码
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
# mc 命令来内存编译修改过的代码(使用mc命令来编译jad的反编译的代码有可能失败。最好本地编译)
mc /tmp/UserController.java -d /tmp
#用 retransform 命令加载新的字节码
retransform /tmp/com/example/demo/arthas/user/UserController.class
(3)retransform 的限制
不允许新增加 field/method
正在跑的函数,没有退出不能生效(比如死循环)。
14、sysenv:查看jvm环境变量
# 查看所有
sysenv
# 查看单个环境变量
sysenv USER
15、sysprop:查看jvm系统属性
# 查看所有
sysprop
# 查看单个
sysprop java.version
16、trace:监控方法调用与耗时
#参数说明
#参数名称 参数说明
#class-pattern 类名表达式匹配
#method-pattern 方法名表达式匹配
#condition-express 条件表达式
#[E] 开启正则表达式匹配,默认为通配符匹配
#[n:] 命令执行次数,默认值为 100。
# #cost 方法执行耗时
#[m <arg>] 指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch <arg>]。# 监控方法
trace demo.MathGame run
#指定 Class 匹配的最大数量
trace demo.MathGame run -m 1#trace 次数限制
#如果方法调用的次数很多,那么可以用-n参数指定捕捉结果的次数。比如下面的例子里,捕捉到一次调用就退出命令。
trace demo.MathGame run -n 1#包含 jdk 的函数
#--skipJDKMethod <value> skip jdk method trace, default value true.
#默认情况下,trace 不会包含 jdk 里的函数调用,如果希望 trace jdk 里的函数,需要显式设置--skipJDKMethod false。
trace --skipJDKMethod false demo.MathGame run#根据调用耗时过滤
trace demo.MathGame run '#cost > 10'# trace 多个类或者多个函数
trace -E com.test.ClassA|org.test.ClassB method1|method2|method3#排除掉指定的类
#使用 --exclude-class-pattern 参数可以排除掉指定的类,比如:
trace javax.servlet.Filter * --exclude-class-pattern com.demo.TestFilter
# 监控方法
$ trace demo.MathGame run
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 28 ms.
`---ts=2019-12-04 00:45:08;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69`---[0.617465ms] demo.MathGame:run()`---[0.078946ms] demo.MathGame:primeFactors() #24 [throws Exception]`---ts=2019-12-04 00:45:09;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69`---[1.276874ms] demo.MathGame:run()`---[0.03752ms] demo.MathGame:primeFactors() #24 [throws Exception]
17、tt:记录方法参数
# 记录方法
tt -t demo.MathGame primeFactors
# 查看所有记录
$ tt -lINDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
-------------------------------------------------------------------------------------------------------------------------------------1000 2018-12-04 11:15:38 1.096236 false true 0x4b67cf4d MathGame primeFactors1001 2018-12-04 11:15:39 0.191848 false true 0x4b67cf4d MathGame # 我需要筛选出 primeFactors 方法的调用信息
$ tt -s 'method.name=="primeFactors"'#查看调用信息
#对于具体一个时间片的信息而言,你可以通过 -i 参数后边跟着对应的 INDEX 编号查看到他的详细信息。
$ tt -i 1003# 重新调用一次函数
tt -i 1004 -p
18、vmtool:停止线程、强制GC
#强制 GC
vmtool --action forceGc#interrupt 指定线程
#thread id 通过-t参数指定,可以使用 thread命令获取。
vmtool --action interruptThread -t 1
19、watch:监控函数参数
让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参
,通过编写 OGNL 表达式进行对应变量的查看。