阿里巴巴Arthas详解
目录
Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6+, 采用命令行交互模式,可以方便的定位和诊断线上程序运行问题。
官方文档:
https://arthas.aliyun.com/doc/
GitHub 地址:
https://github.com/alibaba/arthas
一 Arthas使用场景
得益于 Arthas 强大且丰富的功能,让 Arthas 能做的事情超乎想象。下面仅仅列举几项常见的使用情况,更多的使用场景可以在熟悉了 Arthas 之后自行探索。
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到 JVM 的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
- 怎样直接从 JVM 内查找某个类的实例?
二 Arthas下载及启动
# github下载arthas
wget https://alibaba.github.io/arthas/arthas-boot.jar
# 或者 Gitee 下载
wget https://arthas.gitee.io/arthas-boot.jar
用java -jar运行即可,可以识别机器上所有Java进程(我们这里之前已经运行了一个Arthas测试程序,代码见下方)
java -jar arthas-boot.jar
或者
sudo java -jar arthas-boot.jar
ps: 异常解决
Can not find java process. Try to run `jps` command lists the instrumented Java HotSpot VMs on the target system. Please select an available pid
可能是没有权限,使用 sudo 启动
测试代码
import java.util.HashSet;
public class Arthas {
private static HashSet hashSet = new HashSet();
public static void main(String[] args) {
// 模拟 CPU 过高
cpuHigh();
// 模拟线程死锁
deadThread();
// 不断的向 hashSet 集合增加数据
addHashSetThread();
}
/**
* 不断的向 hashSet 集合添加数据
*/
public static void addHashSetThread() {
// 初始化常量
new Thread(() -> {
int count = 0;
while (true) {
try {
hashSet.add("count" + count);
Thread.sleep(1000);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public static void cpuHigh() {
new Thread(() -> {
while (true) {
}
}).start();
}
/**
* 死锁
*/
private static void deadThread() {
/** 创建资源 */
Object resourceA = new Object();
Object resourceB = new Object();
// 创建线程
Thread threadA = new Thread(() -> {
synchronized (resourceA) {
System.out.println(Thread.currentThread() + " get ResourceA");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resourceB");
synchronized (resourceB) {
System.out.println(Thread.currentThread() + " get resourceB");
}
}
});
Thread threadB = new Thread(() -> {
synchronized (resourceB) {
System.out.println(Thread.currentThread() + " get ResourceB");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resourceA");
synchronized (resourceA) {
System.out.println(Thread.currentThread() + " get resourceA");
}
}
});
threadA.start();
threadB.start();
}
}
三 快速入门
01 选择应用 java 进程
选择进程序号1,进入进程信息操作
02 查看 dashboard
输入dashboard可以查看整个进程的运行情况,线程、内存、GC、运行环境信息:
dashboard
03 查看线程详细情况
输入thread可以查看线程详细情况
thread
04 查看指定线程堆栈
输入 thread加上线程ID 可以查看线程堆栈
thread 35
05 查看线程死锁
输入 thread -b 可以查看线程死锁
thread -b
06 反编译
输入 jad加类的全名 可以反编译,这样可以方便我们查看线上代码是否是正确的版本
jad com.hjxr.algorithm.leetCode.ConvertTest6
7 退出
exit