点击上方蓝字关注我们
IT 咖啡馆,探索无限可能!
恭喜你发现了这个宝藏,这里你会发现优质的开源项目、IT知识和有趣的内容。
Java是大型项目的热门开发语言,尤其是在国内,如果在生产环境中遇到问题,无法使用 IDE 远程调试,那该怎么办呢?
今天我们分享一个阿里开源的项目,它让开发人员可以在线解决生产问题。无需 JVM 重启,无需代码更改,它就是:arthas
arthas 是什么
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
Arthas
是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。
当你遇到以下类似问题而束手无策时,Arthas
可以帮助你解决:
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
是否有一个全局视角来查看系统的运行状况?
有什么办法可以监控到 JVM 的实时运行状态?
怎么快速定位应用的热点,生成火焰图?
怎样直接从 JVM 内查找某个类的实例?
安装 arthas
Arthas
支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab
自动补全功能,arthas 支持多种安装方式。
arthas-boot
arthas-boot
首先arthas推荐使用**arthas-boot
,使用方式非常简单,**下载arthas-boot.jar
,然后用java -jar
的方式启动,命令参考如下:
curl -O <https://arthas.aliyun.com/arthas-boot.jar>
java -jar arthas-boot.jar
如果感觉下载的速度太慢,可以使用 aliyun 的镜像:
java -jar arthas-boot.jar --repo-mirror aliyun --use-http
as.sh安装
Arthas 支持在 Linux/Unix/Mac 等平台上一键安装,可以通过使用以下的一键安装脚本,来快速安装:
curl -L <https://arthas.aliyun.com/install.sh> | sh
上述命令会下载启动脚本文件as.sh
到当前目录,你可以放在任何地方或将其加入到$PATH
中。
直接在 shell 下面执行./as.sh
,就会进入交互界面。
也可以执行./as.sh -h
来获取更多参数信息。
全量安装
你可以在官方的下载地址下载Arthas 的包:https://arthas.aliyun.com/download/latest_version?mirror=aliyun
解压后,在文件夹里有arthas-boot.jar
,直接用java -jar
的方式启动。
使用 arthas
首先如果你还没有完成上面的安装,也可以先来体验和试用,项目提供了在线的教程,它可以逐步让你掌握这款工具。用的是killercoda,这里我在用的时候遇到个问题,arthas网站内嵌的killercoda会无法认证登录,你可以直接访问killercoda,登录后自己搜arthas的课程即可。
1. 启动 math-game
curl -O <https://arthas.aliyun.com/math-game.jar>
java -jar math-game.jar
math-game
是一个简单的程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。
2. 启动 arthas
在命令行下面执行(使用和目标进程一致的用户启动,否则可能 attach 失败):
curl -O <https://arthas.aliyun.com/arthas-boot.jar>
java -jar arthas-boot.jar
执行该程序的用户需要和目标进程具有相同的权限。比如以
admin
用户来执行:sudo su admin && java -jar arthas-boot.jar
或sudo -u admin -EH java -jar arthas-boot.jar
。如果 attach 不上目标进程,可以查看
~/logs/arthas/
目录下的日志。java -jar arthas-boot.jar -h
打印更多参数信息。
选择应用 java 进程:
$ $ java -jar arthas-boot.jar
* [1]: 35542
[2]: 71560 math-game.jar
math-game
进程是第 2 个,则输入 2,再输入回车/enter
。Arthas 会 attach 到目标进程上,并输出日志:
3. 查看 dashboard
Arthas 提供一个实时查看系统运行状况的 Dashboard,方便开发者实时监控系统的负载、内存使用情况、GC 状态和线程状态。我平时一边干其他事一边还要盯着系统负载,有了 Dashboard,简直轻松愉快。
4. thread 命令
thread 可以用来查看当前线程信息,查看线程的堆栈。
thread 1
会打印线程 ID 1 的栈,通常是 main 函数的线程。通过 thread 命令来获取到math-game
进程的 Main Class
5. jad 反编译
$ jad demo.MathGame
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@3d4eac69
+-sun.misc.Launcher$ExtClassLoader@66350f69
Location:
/tmp/math-game.jar
/*
* Decompiled with CFR 0_132.
*/
package demo;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class MathGame {
private static Random random = new Random();
private int illegalArgumentCount = 0;
public static void main(String[] args) throws InterruptedException {
MathGame game = new MathGame();
do {
game.run();
TimeUnit.SECONDS.sleep(1L);
} while (true);
}
public void run() throws InterruptedException {
try {
int number = random.nextInt();
List<Integer> primeFactors = this.primeFactors(number);
MathGame.print(number, primeFactors);
}
catch (Exception e) {
System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());
}
}
public static void print(int number, List<Integer> primeFactors) {
StringBuffer sb = new StringBuffer("" + number + "=");
Iterator<Integer> iterator = primeFactors.iterator();
while (iterator.hasNext()) {
int factor = iterator.next();
sb.append(factor).append('*');
}
if (sb.charAt(sb.length() - 1) == '*') {
sb.deleteCharAt(sb.length() - 1);
}
System.out.println(sb);
}
public List<Integer> primeFactors(int number) {
if (number < 2) {
++this.illegalArgumentCount;
throw new IllegalArgumentException("number is: " + number + ", need >= 2");
}
ArrayList<Integer> result = new ArrayList<Integer>();
int i = 2;
while (i <= number) {
if (number % i == 0) {
result.add(i);
number /= i;
i = 2;
continue;
}
++i;
}
return result;
}
}
Affect(row-cnt:1) cost in 970 ms.
6. watch
通过watch命令来查看demo.MathGame#primeFactors
函数的返回值:
还有其他更多的命令,可以查看官方文档。
7.profiler
profiler
命令支持生成应用热点的火焰图。本质上是通过不断的采样,然后把收集到的采样结果生成火焰图。
profiler
命令基本运行结构是 profiler action [actionArg]
默认情况下,结果是 Flame Graph 格式的 html 文件,也可以用 -o 或 --format 参数指定其他内容格式,包括 flat、traces、collapsed、flamegraph、tree、jfr。
原理解析
通过上面的使用示例,我们看到 arthas 并不需要对原有的进行有什么动作,那么如何实现的呢?
它的主要原理是通过字节码增强技术来实现对 Java 应用程序的监控和诊断。具体来说,arthas会在运行时动态地修改 Java 字节码,插入一些额外的代码逻辑,从而实现对应用程序的各种监控和诊断功能。
当 arthas被启动时,它会将自己嵌入到 Java 进程中,并加载一个特定的 Agent。这个 Agent 会在运行时动态地修改 Java 字节码,插入一些额外的代码逻辑。这些额外的代码逻辑会在应用程序的运行过程中被执行,从而实现对应用程序的监控和诊断。
arthas提供了一系列的命令,这些命令可以通过命令行或 HTTP API 来发送。当用户发送一个命令时,arthas会根据这个命令在运行时执行相应的监控和诊断操作,并将结果返回给用户。
例如,当用户发送一个“trace”命令时,arthas会在运行时动态地修改字节码,插入一些额外的代码逻辑来跟踪方法的调用。这些额外的代码逻辑会在方法被调用时记录下方法的入参、出参、执行时间等信息,并将这些信息返回给用户。通过分析这些信息,用户可以了解方法的执行情况,找出性能瓶颈等问题。
一句话概括就是arthas使用java agent技术连接应用程序,给自己开了一个后门,然后使用字节码增强技术来实现相应的监控和诊断操作。
总结
整体来说arthas可以解决很多java开发者的调试难题,尤其是对于不能轻易改动的环境,通过arthas可以发现和诊断出问题所在。同时由于是阿里开源的项目,本身项目的质量还是很有保障的,所以非常值得大家学习和参考。
项目信息
项目名称:arthas
GitHub 链接:https://github.com/alibaba/arthas
Star 数:35K