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

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的方式启动,命令参考如下:

arduino 复制代码
curl -O <https://arthas.aliyun.com/arthas-boot.jar>
java -jar arthas-boot.jar

如果感觉下载的速度太慢,可以使用 aliyun 的镜像:

css 复制代码
java -jar arthas-boot.jar --repo-mirror aliyun --use-http

as.sh安装

Arthas 支持在 Linux/Unix/Mac 等平台上一键安装,可以通过使用以下的一键安装脚本,来快速安装:

arduino 复制代码
curl -L <https://arthas.aliyun.com/install.sh> | sh

上述命令会下载启动脚本文件 as.sh 到当前目录,你可以放在任何地方或将其加入到 $PATH 中。

直接在 shell 下面执行./as.sh,就会进入交互界面。

也可以执行./as.sh -h来获取更多参数信息。

全量安装

你可以在官方的下载地址下载Arthas 的包:arthas.aliyun.com/download/la...

解压后,在文件夹里有arthas-boot.jar,直接用java -jar的方式启动。

使用 arthas

首先如果你还没有完成上面的安装,也可以先来体验和试用,项目提供了在线的教程,它可以逐步让你掌握这款工具。用的是killercoda,这里我在用的时候遇到个问题,arthas网站内嵌的killercoda会无法认证登录,你可以直接访问killercoda,登录后自己搜arthas的课程即可。

1. 启动 math-game

lua 复制代码
curl -O <https://arthas.aliyun.com/math-game.jar>
java -jar math-game.jar

math-game是一个简单的程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。

2. 启动 arthas

在命令行下面执行(使用和目标进程一致的用户启动,否则可能 attach 失败):

arduino 复制代码
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 进程:

ini 复制代码
$ $ 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 命令来获取到math-game进程的 Main Class

thread 可以用来查看当前线程信息,查看线程的堆栈。

thread 1会打印线程 ID 1 的栈,通常是 main 函数的线程。

5. 通过 jad 来反编译 Main Class

java 复制代码
$ 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可以发现和诊断出问题所在。同时由于是阿里开源的项目,本身项目的质量还是很有保障的,所以非常值得大家学习和参考。

项目信息

相关推荐
Ylucius3 分钟前
常见服务器大全----都是什么?又有何作用?区别联系是什么?---web,应用,数据库,文件,消息队列服务器,Tomat,Nginx,vite.....
java·前端·javascript·chrome·学习·node.js·express
茜茜西西CeCe7 分钟前
移动技术开发:RecyclerView瀑布流水果列表
android·java·安卓·android-studio·recycleview·移动技术开发
熙曦Sakura1 小时前
【C/C++】错题记录(一)
java·c语言·c++
无极程序员2 小时前
读取到json数据拿出来,修改后重新写入json文件
android·java·开发语言·后端·json·php
艾伦~耶格尔2 小时前
Java 之 ssm框架入门
java·开发语言·后端·spring·mybatis·ssm
尘浮生2 小时前
Java项目实战II基于Java+Spring Boot+MySQL的美容院管理系统设计与实现(源码+数据库+文档)
java·开发语言·数据库·spring boot·mysql·maven·intellij-idea
曳渔2 小时前
Java-数据结构-Map和Set-(二)-哈希表 |ू・ω・` )
java·开发语言·数据结构·算法·哈希算法·散列表
杰克尼2 小时前
Java五子棋
java·开发语言
March€2 小时前
常见算法复习
java·算法·排序算法