官方地址: https://arthas.aliyun.com

简介

简介

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

背景

通常,本地开发环境无法访问生产环境。如果在生产环境中遇到问题,则无法使用 IDE 远程调试。更糟糕的是,在生产环境中调试是不可接受的,因为它会暂停所有线程,导致服务暂停。

开发人员可以尝试在测试环境或者预发环境中复现生产环境中的问题。但是,某些问题无法在不同的环境中轻松复现,甚至在重新启动后就消失了。

如果您正在考虑在代码中添加一些日志以帮助解决问题,您将必须经历以下阶段:测试、预发,然后生产。这种方法效率低下,更糟糕的是,该问题可能无法解决,因为一旦 JVM 重新启动,它可能无法复现,如上文所述。

Arthas 旨在解决这些问题。开发人员可以在线解决生产问题。无需 JVM 重启,无需代码更改。 Arthas 作为观察者永远不会暂停正在运行的线程。

Arthas(阿尔萨斯)能为你做什么? Arthas 是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。

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

  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
  2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
  3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
  4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
  5. 是否有一个全局视角来查看系统的运行状况?
  6. 有什么办法可以监控到 JVM 的实时运行状态?
  7. 怎么快速定位应用的热点,生成火焰图?
  8. 怎样直接从 JVM 内查找某个类的实例?
  9. Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

Arthas Install

使用arthas-boot(推荐)

下载arthas-boot.jar,然后用java -jar的方式启动:

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

打印帮助信息:

java -jar arthas-boot.jar -h
  • 如果下载速度比较慢,可以使用 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来获取更多参数信息。

快速入门

快速入门

  1. 执行一个jar包
  2. 通过arthas来粘附,并且进行几种常用的操作
  3. 通过一个案例快速入门

以下是一个简单的Java程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。代码 的内容不用理会这不是现在关注的点


package com.tiplus.api.web;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class MathGame {
    private static Random random = new Random();
    public int illegalArgumentCount = 0;

    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;
    }

    public static void main(String[] args) throws InterruptedException {
        MathGame game = new MathGame();
        do {
            game.run();
            TimeUnit.SECONDS.sleep(1L);
            System.out.println("在main函数中循环体内");
        } while (true);
    }

    public void run() throws InterruptedException {
	System.out.println("-- 计算中的函数 -- ");
        try {
            int number = random.nextInt() / 10000;
            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 + "=");
        for (int factor : primeFactors) {
            sb.append(factor).append('*');
        }
        if (sb.charAt(sb.length() - 1) == '*') {
            sb.deleteCharAt(sb.length() - 1);
        }
        System.out.println(sb);
    }
}


选择应用 java 进程:

$ $ java -jar arthas-boot.jar
* [1]: 35542
  [2]: 71560 math-game.jar

查看 dashboard 输入dashboard,按回车/enter,会展示当前进程的信息,按ctrl+c可以中断执行。

$ dashboard
ID     NAME                   GROUP          PRIORI STATE  %CPU    TIME   INTERRU DAEMON
17     pool-2-thread-1        system         5      WAITIN 67      0:0    false   false
27     Timer-for-arthas-dashb system         10     RUNNAB 32      0:0    false   true
11     AsyncAppender-Worker-a system         9      WAITIN 0       0:0    false   true
9      Attach Listener        system         9      RUNNAB 0       0:0    false   true
3      Finalizer              system         8      WAITIN 0       0:0    false   true
2      Reference Handler      system         10     WAITIN 0       0:0    false   true
4      Signal Dispatcher      system         9      RUNNAB 0       0:0    false   true
26     as-command-execute-dae system         10     TIMED_ 0       0:0    false   true
13     job-timeout            system         9      TIMED_ 0       0:0    false   true
1      main                   main           5      TIMED_ 0       0:0    false   false
14     nioEventLoopGroup-2-1  system         10     RUNNAB 0       0:0    false   false
18     nioEventLoopGroup-2-2  system         10     RUNNAB 0       0:0    false   false
23     nioEventLoopGroup-2-3  system         10     RUNNAB 0       0:0    false   false
15     nioEventLoopGroup-3-1  system         10     RUNNAB 0       0:0    false   false
Memory             used   total max    usage GC
heap               32M    155M  1820M  1.77% gc.ps_scavenge.count  4
ps_eden_space      14M    65M   672M   2.21% gc.ps_scavenge.time(m 166
ps_survivor_space  4M     5M    5M           s)
ps_old_gen         12M    85M   1365M  0.91% gc.ps_marksweep.count 0
nonheap            20M    23M   -1           gc.ps_marksweep.time( 0
code_cache         3M     5M    240M   1.32% ms)
Runtime
os.name                Mac OS X
os.version             10.13.4
java.version           1.8.0_162
java.home              /Library/Java/JavaVir
                       tualMachines/jdk1.8.0
                       _162.jdk/Contents/Hom
                       e/jre

web:http://127.0.0.1:3658/

常用命令入门

dashboard仪表盘

注:输入前面部分字母,按tab可以自动补全命令

  1. 第一部分是显示JVM中运行的所有线程:所在线程组,优先级,线程的状态,CPU的占用率,是 否是后台进程等
  2. 第二部分显示的JVM内存的使用情况
  3. 第三部分是操作系统的一些信息和Java版本号 1.png

thread 查看当前线程信息,查看线程的堆栈

333.png

jad 反编译指定已加载类的源码

44.png

watch 函数执行数据观测-debug使用(程序实际运行使用)

让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。

watch demo.MathGame primeFactors returnObj

基础命令

help 查看命令帮助信息,可以查看当前 arthas 版本支持的指令,或者查看具体指令的使用说明。

cat 打印文件内容,和 linux 里的 cat 命令类似。

grep 类似传统的grep命令。

pwd 返回当前的工作目录,和 linux 命令类似

cls 清空当前屏幕区域。

session 查看当前会话的信息,显示当前绑定的 pid 以及会话 id。

reset 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端stop时会重置所有增强过的类

version 输出当前目标 Java 进程所加载的 Arthas 版本号

quit 退出当前 Arthas 客户端,其他 Arthas 客户端不受影响。等同于exit、logout、q三个指令。

stop 关闭 Arthas 服务端,所有 Arthas 客户端全部退出。

keymap 命令输出当前的快捷键映射表:

jvm相关

dashboard 仪表板

6.png

  • ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应
  • NAME: 线程名
  • GROUP: 线程组名
  • PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
  • STATE: 线程的状态
  • CPU%: 线程消耗的cpu占比,采样100ms,将所有线程在这100ms内的cpu使用量求和,再算出每个线程的cpu使用占比。
  • TIME: 线程运行总时间,数据格式为 分:秒
  • INTERRUPTED: 线程当前的中断位状态
  • DAEMON: 是否是daemon线程

thread 线程

查看当前线程信息,查看线程的堆栈

参数名称	参数说明
id	线程 id
[n:]	指定最忙的前 N 个线程并打印堆栈
[b]	找出当前阻塞其他线程的线程
[i <value>]	指定 cpu 使用率统计的采样间隔,单位为毫秒,默认值为 200
[--all]	显示所有匹配的线程

jvm 虚拟机 查看当前 JVM 信息

  • THREAD相关
    • COUNT: JVM当前活跃的线程数
    • DAEMON-COUNT: JVM当前活跃的守护线程数
    • PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数
    • STARTED-COUNT: 从JVM启动开始总共启动过的线程次数
    • DEADLOCK-COUNT: JVM当前死锁的线程数
    • 指定采样时间间隔,每过1000毫秒采样,显示最占时间的3个线程 thread -i 1000 -n 3 1 2
  • 查看处于等待状态的线程 thread --state WAITING 1 2
  • 文件描述符相关
    • MAX-FILE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符数
    • OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数

sysprop 系统属性

查看当前 JVM 的系统属性(System Property)

sysenv 查看当前JVM的环境属性( System Environment Variables )

vmoption 查看,更新VM诊断相关的参数

getstatic 通过getstatic命令可以方便的查看类的静态属性

ognl 执行 ognl 表达式

class/classloader相关

sc 查看 JVM 已加载的类信息

Search-Class” 的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,这个命令支持的参数有[d]、[E]、[f] 和 [x:]。

sm 查看已加载类的方法信息

“Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。 sm 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到。

jad 查看已加载类的方法信息 反编译

jad 命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于你理解业务逻辑; 在 Arthas Console 上,反编译出来的源码是带语法高亮的,阅读更方便 当然,反编译出来的 java 代码可能会存在语法错误,但不影响你进行阅读理解

mc Memory Compiler/内存编译器,编译.java文件生成.class。

redefine 加载外部的 .class 文件,redefine到JVM里

retransform 加载外部的.class文件,retransform jvm 已加载的类。

dump dump 已加载类的 bytecode 到特定目录

classloader 查看 classloader 的继承树,urls,类加载信息

classloader 命令将 JVM 中所有的 classloader 的信息统计出来,并可以展示继承树,urls 等。 可以让指定的 classloader 去 getResources,打印出所有查找到的 resources 的 url。对于ResourceNotFoundException比较有用。

monitor/watch/trace相关

monitor方法执行监控

对匹配 class-pattern/method-pattern/condition-express的类、方法的调用进行监控。 monitor 命令是一个非实时返回命令. 实时返回命令是输入之后立即返回,而非实时返回的命令,则是不断的等待目标 Java 进程返回信息,直到用户输入 Ctrl+C 为止。 服务端是以任务的形式在后台跑任务,植入的代码随着任务的中止而不会被执行,所以任务关闭后,不会对原有性能产生太大影响,而且原则上,任何 Arthas 命令不会引起原有业务逻辑的改变。

watch 函数执行数据观测

让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。

trace方法内部调用路径,并输出方法路径上的每个节点上耗时

trace 命令能主动搜索 class-pattern/method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。

stack 输出当前方法被调用的调用路径

很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令