Arthas学习
文章目录
安装使用
(1)安装
|  |  | 

(2)退出Arthas
直接运行 quit 或者 exit 命令。但是这不是退出 Arthas ,而是退出当前连接而已,下次还是可以继续连接 Arthas 。想完全退出 Arthas,需要使用 stop 或者 shutdown 命令;
常用命令
(1)查看仪表盘
直接运行 dashboard ,这个主要是帮助我们发现性能问题:

(2)修改日志级别
直接输入 logger 命令即可查看logger信息,包括日志的位置,对于查看系统的日志位置非常方便:

此外, logger 命令还可以用于修改日志级别:
| 参数 | 说明 | 
|---|---|
| -c | 指定 classloader的 hash ,默认为SystemClassLoader,例如:logger -c 1654a892 | 
| -l | 设置日志级别,例如: logger -n debug -c 1654a892 -l debug | 
| -n | 获取指定名称logger的信息,例如: logger -n debug | 
(3)下载内存
可以使用 heapdump 命令下载程序的运行时内存,参数说明如下:
| 参数 | 说明 | 
|---|---|
| -l | 只dump内存中的live对象,例如: heapdump -l /tmp/dump.hprof | 
| [file] | 指定输出文件,例如: heapdump /tmp/dump.hprof | 
(4)反编译
直接使用 jad xxx.xxx.xxx.XXX 来反编译某个类:

(5)动态修改类
这个功能相关的命令为: retransform ,其限制如下:
- 不允许新增加 field或者method;
- 正在跑的函数,没有退出不能生效;
参数说明:
| 参数 | 说明 | 
|---|---|
| -c | 指定classloader加载文件,例如: retransform -c 327a647b /tmp/Test.class /tmp/Test\$Inner.class | 
| –classPattern [value] | 触发重新加载class文件,例如: retransform --classPattern demo.* | 
| -d | 删除指定id替换的条目,例如: retransform -d 1 | 
| –deleteAll | 删除所有替换的条目,例如: retransform --deleteAll | 
| -l | 列出所有替换的条目,例如: retransform -l | 
| [classfilePaths] | 加载指定路径的class文件,例如: retransform /tmp/Test.class | 
如果需要还原修改后的类:
|  |  | 
(6)观察方法调用
这个功能相关的命令为: watch ;相关参数和介绍如下:
| 参数 | 说明 | 
|---|---|
| class-pattern | 类名表达式匹配 | 
| method-pattern | 方法名表达式匹配 | 
| express | 观察表达式 | 
| condition-express | 条件表达式 | 
| [b] | 在方法调用之前观察 | 
| [e] | 在方法异常之后观察 | 
| [s] | 在方法返回之后观察 | 
| [f] | 在方法结束之后(正常返回和异常返回)观察 | 
| [E] | 开启正则表达式匹配,默认为通配符匹配 | 
| [x:] | 指定输出结果的属性遍历深度,默认为 1 | 
注意点:
- watch命令定义了4个观察事件点,即- -b方法调用前,- -e方法异常后,- -s方法返回后,- -f方法结束后;
- 4个观察事件点 -b、-e、-s默认关闭,-f默认打开,当指定观察点被打开后,在相应事件点会对观察表达式进行求值并输出;
- 这里要注意方法入参和方法出参的区别,有可能在中间被修改导致前后不一致,除了-b事件点params代表方法入参外,其余事件都代表方法出参;
- 当使用 -b时,由于观察事件点是在方法调用前,此时返回值或异常均不存在;
例如使用如下命令观察方法入参和返回的参数:
|  |  | 

一些案例场景可以查看:https://github.com/alibaba/arthas/issues/71
Arthas中Ognl默认支持的变量为如下:
|  |  | 
(7)观察方法调用路径
trace 命令能主动搜索 class-pattern/method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。
参数说明如下:
| 参数名称 | 参数说明 | 
|---|---|
| class-pattern | 类名表达式匹配 | 
| method-pattern | 方法名表达式匹配 | 
| condition-express | 条件表达式 | 
| [E] | 开启正则表达式匹配,默认为通配符匹配 | 
| [n:] | 命令执行次数 | 
| #cost | 方法执行耗时 | 
注意:watch , stack , trace 这个三个命令都支持 #cost 。
例如使用如下命令查看某个函数的调用路径,但是貌似只能查看目标函数的栈顶调用路径,不能看到栈低的调用路径,也就是说,不能查看是谁调用到了目标函数:
|  |  | 

(8)查看ClassLoader
使用 classloader 命令可以查看classloader的继承树,urls,类加载信息;例如使用如下命令查看classloader统计信息:
|  |  | 

查看classloader的继承树:
|  |  | 

(9)内存编译
使用 mc 命令可以编译 .java 文件生成 .class ;可以使用 -c 选项指定classloader:
|  |  | 
也可以通过--classLoaderClass参数指定ClassLoader:
|  |  | 
编译生成 .class 文件之后,可以结合 retransform 命令实现热更新代码。
注意:mc 命令有可能失败。如果编译失败可以在本地编译好 .class 文件,再上传到服务器。
(10)查看方法调用栈
前面说过可以通过 trace 命令查看方法调用路径,但是这样只能得到从当前方法往下执行的调用路径,如果想得到完整的方法调用栈,需要使用 stack 命令:
|  |  | 

一些参数说明如下:
| 参数名称 | 参数说明 | 
|---|---|
| class-pattern | 类名表达式匹配 | 
| method-pattern | 方法名表达式匹配 | 
| condition-express | 条件表达式 | 
| [E] | 开启正则表达式匹配,默认为通配符匹配 | 
| [n:] | 执行次数限制 | 
注意事项
- JVM只能 attach 同样用户下的 java 进程,需要切换到目标- JVM相同的用户下,才能使用,或者使用某个用户的身份执行命令:- java -jar arthas-boot.jar --telnet-port 9998 --http-port -1;
参考
文章作者 P1n93r
上次更新 2021-06-15