Arthas 是由阿里巴巴开源,在线排查问题,无需重启;动态跟踪 Java 代码;实时监控 JVM 状态。(Arthas官方地址)
一、Arthas 的六大特性
- Dashboard:实时查看Java服务的运行状况;
- 查看入参/返回值/异常:可实时查看方法调用的入参、返回值、异常;
- 在线热更新:jad -> sc -> redefine 一条龙热更新代码;
- 类冲突:秒解类冲突问题,定位类加载路径;
- 性能热点:快速定位应用的热点,生成火焰图;
- Webconsole:在线诊断,点开网页及时诊断线上应用;
二、Arthas 实践
1. dashboard命令
使用dashboard命令可以获取当前Java服务的运行状态信息,如线程状况,GC情况等。
- 使用命令启动arthas,
java -jar arthas-boot.jar
- 找到arthas 进程要附加的目标进程,输入该进程对应序号;
- 输入
dashboard
命令,可以观察到 Java 服务的配置信息如下;
2. thread 命令
查看当前线程信息,查看线程的堆栈。
thread -n 2
:显示当前最忙的2个线程,并打印出线程栈。
thread {id}
: thread + 线程ID,显示出指定ID的线程具体情况。下面以线程ID为25为例。
3. watch 命令
用于方法执行过程中的数据观测。可观测的数据包括入参、返回值、抛出的异常。可根据不同的参数选项来决定观测不同的参数。除此之外,还有4个观测点(观测时机),通过如下4个参数指定指定观测点,默认仅 -f
生效。
-b
: 方法被调用之前;
-e
: 异常抛出后;
-f
: 方法执行完成后,默认生效。
-s
: 方法返回之后;
3.1 观察指定方法的返回值
watch {full_class_name} {method_name} -x {n}
:
{full_class_name}
: 全限定类名;
{method_name}
: 指定类下的方法名;
-x
: 该选项后面跟一个数字,用于指定返回对象结果的递归深度;
该条命令表示要观测指定类中某方法的返回值,且对返回值对象内容递归 {n}
层的深度,该命令示例如下:
3.2 观察指定方法的入参、返回值
watch {full_class_name} {method_name} "{params, returnObj}" -x {n} -b
:
{full_class_name}
: 全限定类名;
{method_name}
: 指定类下的方法名;
{params, returnObj}
: 要求打印出入参和返回值;
-x
: 该选项后面跟一个数字,用于指定返回对象结果的递归深度;
-b
: 使用该参数表示增加方法调用前观测点。默认已使用-f
选项;
该条命令表示要观测指定类下某个方法的入参和返回值,且对返回值对象内容递归 {n}
层的深度,该命令示例如下:
3.3 观察指定方法的执行耗时
watch {full_class_name} {method_name} "{params, returnObj}" "#cost>{t}" -x {n}
:
{full_class_name}
: 全限定类名;
{method_name}
: 指定类下的方法名;
{params, returnObj}
: 要求打印出入参和返回值;
"#cost>{t}"
:{t}
是自己设置的时间段长度,默认单位是ms,
-x
: 该选项后面跟一个数字,用于指定返回对象结果的递归深度;
该条命令表示输出方法执行的耗时超过指定值的入参、返回值,并且参数对象的输出递归深度也被指定。下面是命令执行示例。
4. jad 命令
反编译指定已加载类的源码
jad {full_class_name}
{full_class_name}
: 要进行反编译的类文件的全限定类名;
下面以对 Integer 类进行反编译为例。
5. sc 命令
查看 JVM 已加载的类信息
5.1 模糊搜索已加载的类
sc demo.*
模糊搜索以
demo.
为全限定类名前缀的类
执行示例:
5.2 输出类的详细信息
sc -d demo.MathGame
输出类demo.MathGame的详细信息。
执行示例:
5.3 输出类的详细信息
sc -d -f demo.MathGame
输出类demo.MathGame及其字段的详细信息。
执行示例如下,与不加 -f
选项相比多出来红框框住的字段信息部分。
6. redefine 命令
加载外部的 .class
文件,覆盖 JVM 已加载的类。
redefine /tmp/Animal.class
redefine 指定目录下的字节码文件
redefine
命令的限制
- 不能新增 field/method;
- 正在运行的方法,没有退出的话,运行该命令不会生效;
7. 使用 Arthas 定位 CPU 飚高问题
- 先使用
dashboard
命令查看服务大概状况:
- 使用
thread -n 2
命令查看耗CPU 最多的2个线程,可以看到第一个线程的CPU 使用率就达到了 98%。从下图该线程栈可以看出,造成使用率这么高的源码文件路径为:com.fuyou.arthaspractice.Application
。
- 使用
jad
命令对该文件进行反编译。从截图可以看出,这个文件是服务的启动类,其逻辑也非常简单,就是实现了一个死循环,不断地输出“Do Nothing.”。
- 使用
jad --source-only
命令获取该类源码。
- 使用 vim 修改定位到的BUG,此处在循环内加入sleep函数,每执行一次,sleep 3秒。
- 使用
mc
命令对该源文件重新编译。mc
命令的执行经常会出现问题,此时可将源文件本地编译之后再上传。
mc /root/Application.java -d /root/
- 将编译好的字节码文件使用
redefine
命令重新加载到内存:
ps:因为使用 redefine
命令重新加载字节码对正在运行的方法无法生效,使用该示例演示不太合适,仅起演示作用。