35K star!生产环境的Java诊断工具,阿里开源神器

文摘   科技   2024-08-13 16:39   北京  

点击上方蓝字关注我们

IT 咖啡馆,探索无限可能!

恭喜你发现了这个宝藏,这里你会发现优质的开源项目、IT知识和有趣的内容。

 

Java是大型项目的热门开发语言,尤其是在国内,如果在生产环境中遇到问题,无法使用 IDE 远程调试,那该怎么办呢?

今天我们分享一个阿里开源的项目,它让开发人员可以在线解决生产问题。无需 JVM 重启,无需代码更改,它就是:arthas



arthas 是什么



Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。

Arthas 是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。

当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:

  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?

  2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?

  3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?

  4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!

  5. 是否有一个全局视角来查看系统的运行状况?

  6. 有什么办法可以监控到 JVM 的实时运行状态?

  7. 怎么快速定位应用的热点,生成火焰图?

  8. 怎样直接从 JVM 内查找某个类的实例?





安装 arthas



Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,arthas 支持多种安装方式。

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



往期推荐

37K star!实时后端服务,一个文件实现

54K star!网站状态监控轻松搞定,小巧且强大

「Github一周热点32期」动画图解算法教程、用LLM写完整报告等5个项目


  




识别二维码关注我们
微信号- it-coffee
B站 - IT-咖啡馆
头条号- IT咖啡馆

IT咖啡馆
开源项目、IT技能和有趣的事情
 最新文章