什么是Arthas
Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。
当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
是否有一个全局视角来查看系统的运行状况?
有什么办法可以监控到JVM的实时运行状态?
怎么快速定位应用的热点,生成火焰图?
怎样直接从JVM内查找某个类的实例?
Arthas支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。
本文通过对比传统排查方法和使用Arthas方法进行对比来介绍Arthas工具。
前期准备
首先准备一份Java代码,代码内容很简单,制造一个死循环,使cpu保持在较高的使用率上
import java.util.concurrent.*;
public class CpuDemo {
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(1, 1,
1L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
threadPool.submit(() -> {
while (true) {
compute();
}
});
}
private static int compute() {
int a = 2048;
int b = 1024;
return (a + b) * 10;
}
}
将CpuDemo.java文件上传至Linux虚拟机中,并进行编译启动。
root@sanguo-virtual-machine:/home# javac CpuDemo.java
root@sanguo-virtual-machine:/home# java CpuDemo
我们可以看到 cpu升高并保持在了一个较高的使用率上
传统排查方式
-
使用jps命令打印Java进程
可以看到我们刚才启动的CpuDemo,该步骤是确保我们的项目正常启动。 -
使用top -Hp pid 命令可以查看指定进程的线程信息,然后通过shift+p 按cpu使用率进行排序,查看结果。
可以找到高占用 cpu 的线程 id 10776 -
jstack命令打印线程信息
jstack 10764 |grep $(print "%x\n" 10776) -A 30
查看源代码后发现是compute()方法导致。该方法内是有死循环调用,导致 CPU 过高。问题找到。
使用Arthas
- 下载并运行Arthas
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
-
选择我们要分析的进程
-
可以使用dashboard命令查看整体的情况
我们可以看到,ID为8的线程对cpu的使用率占用最高,因该是这里出现了问题 -
可以通过 thread ID 的命令查看该线程的相关信息
-
也可以使用命令thread -n num 命令 查看占用占用资源做多的num个命令
也可以得到相同的结果 -
若是项目处于线上阶段且项目文件较多。可以通过jad命令来查看该文件所在行的问题
-
热更新代码
在某些项目重启十分繁琐的项目,而又出了bug需要订正的情况下,可以使用redefine命令进行热更新,减少损失。- 使用jad命令反编译出现问题的class
jad --source-only CpuDemo > /home/CpuDemo.java
- 修改问题代码
- 使用redefine命令热更新代码
redefine /home/CpuDemo.class
- 切回刚才在运行的代码后台,发现代码已经更改
- 使用jad命令反编译出现问题的class