Arthas使用方法

一、概述

1、简介

Arthas 是一款基于 Java 开发的开源应用程序诊断工具,可以帮助开发者实时监控和分析 Java 应用程序运行情况,并进行调试和优化。
Arthas 提供了丰富的命令行工具和可视化界面,包括线程堆栈、类加载器、内存使用情况、方法执行时间等多个方面的信息,可以帮助用户快速定位并解决应用程序中的性能问题和异常情况。同时,Arthas 还支持对生产环境中的应用程序进行远程诊断和操作,极大地提高了应用程序的故障排查效率和可靠性。

2、解决问题

当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
是否有一个全局视角来查看系统的运行状况?
有什么办法可以监控到 JVM 的实时运行状态?
怎么快速定位应用的热点,生成火焰图?
怎样直接从 JVM 内查找某个类的实例?

3、与jstackjstatjmap的区别

Arthas、jstack、jstat 和 jmap 都是 Java 调优工具,但它们之间有以下区别:

Arthas 是一款全新的 Java 诊断与调试工具,不仅可以执行传统的 JVM 监控命令,还提供了许多其他高级特性,如实时监控、动态修改代码、反编译等。相比较而言,jstack、jstat 和 jmap 更加基础,只提供了线程栈信息、垃圾回收信息、堆转储信息等。
Arthas 的交互式命令行界面使得开发人员可以通过命令操作来查看和修改目标 JVM 的状态,支持实时监控和动态修改代码,极大地方便了开发和调试过程。而 jstack、jstat 和 jmap 只能通过命令行执行,无法进行实时交互。
Arthas 支持监控线上应用,无需停机,对线上问题快速响应非常有优势。而 jstack、jstat 和 jmap 需要停止 JVM 进程才能进行相关分析。

虽然 Arthas、jstack、jstat 和 jmap 都是 Java 调优工具,但是 Arthas 具有更加强大的功能和交互式的命令行界面,可用于动态修改代码,更适合于在线上环境中进行 JVM 诊断和调试。而 jstack、jstat 和 jmap 更适合本地开发,或者需要停机分析的场景。

4、官方文档

https://arthas.aliyun.com/

二、下载

https://arthas.aliyun.com/arthas-boot.jar

三、快速入门

1、启动 math-game

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

math-game是一个简单的程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。
math-game源代码:https://github.com/alibaba/arthas/blob/master/math-game/src/main/java/demo/MathGame.java

2、启动 arthas

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

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

选择应用 java 进程:

C:\Users\scy\Desktop\arthas>java -jar arthas-boot.jar
[INFO] JAVA_HOME: D:\Program Files\java\jdk1.8.0_171\jre
[INFO] arthas-boot version: 3.6.9
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 2072 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [2]: 11468 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [3]: 18044 oracle.ide.osgi.boot.OracleIdeLauncher
  [4]: 21356 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [5]: 21948 math-game.jar
  [6]: 268

math-game进程是第 5个,则输入 5,再输入回车/enterArthasattach 到目标进程上,并输出日志:

[INFO] arthas home: C:\Users\jiuhui-4\.arthas\lib\3.6.9\arthas
[INFO] Try to attach process 21948
[INFO] Attach process 21948 success.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'

wiki       https://arthas.aliyun.com/doc
tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html
version    3.6.9
main_class
pid        21948
time       2023-06-21 16:20:41

[arthas@21948]$

如果出现如下异常:

[ERROR] Can not read arthas version from: arthas.aliyun.com/api/latest_…
[ERROR] Can not find Arthas under local: /root/.arthas/lib and remote repo mirror: aliyun
[ERROR] Unable to download arthas from remote server, please download the full package according to wiki: github.com/alibaba/art…

按照提示到github上下载完整包。下载地址:https://github.com/alibaba/arthas/releases 到release下载arthas-bin.zip

解压arthas-bin.zip后,直接运行java -jar arthas-boot.jar然后输入对应的java进程序号就可以进行arthas了。

3、查看 dashboard

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

ID   NAME                          GROUP          PRIORITY  STATE    %CPU      DELTA_TIM TIME      INTERRUPT DAEMON
2    Reference Handler             system         10        WAITING  0.0       0.000     0:0.000   false     true
3    Finalizer                     system         8         WAITING  0.0       0.000     0:0.000   false     true
4    Signal Dispatcher             system         9         RUNNABLE 0.0       0.000     0:0.000   false     true
5    Attach Listener               system         5         RUNNABLE 0.0       0.000     0:0.015   false     true
12   arthas-timer                  system         5         WAITING  0.0       0.000     0:0.000   false     true
15   arthas-NettyHttpTelnetBootstr system         5         RUNNABLE 0.0       0.000     0:0.015   false     true
16   arthas-NettyWebsocketTtyBoots system         5         RUNNABLE 0.0       0.000     0:0.000   false     true
17   arthas-NettyWebsocketTtyBoots system         5         RUNNABLE 0.0       0.000     0:0.015   false     true
18   arthas-shell-server           system         5         TIMED_WA 0.0       0.000     0:0.000   false     true
19   arthas-session-manager        system         5         TIMED_WA 0.0       0.000     0:0.000   false     true
20   arthas-UserStat               system         5         WAITING  0.0       0.000     0:0.000   false     true
Memory                    used    total    max     usage    GC
heap                      110M    489M     7234M   1.53%    gc.ps_scavenge.count          0
ps_eden_space             110M    128M     2670M   4.14%    gc.ps_scavenge.time(ms)       0
ps_survivor_space         0K      21504K   21504K  0.00%    gc.ps_marksweep.count         0
ps_old_gen                0K      348160K          0.00%    gc.ps_marksweep.time(ms)      0
nonheap                   27M     28M      -1      97.22%
code_cache                6M      6M       240M    2.55%
metaspace                 19M     20M      -1      97.15%
compressed_class_space    2M      2M       1024M   0.23%
Runtime
os.name                                                     Windows 10
os.version                                                  10.0
java.version                                                1.8.0_171
java.home                                                   D:\Program Files\java\jdk1.8.0_171\jre
systemload.average                                          -1.00
processors                                                  12
timestamp/uptime                                            Wed Jun 21 16:33:43 CST 2023/885s

4、thread 命令

通过 thread 命令来获取到math-game进程的 Main Class

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

[arthas@21948]$ thread 1 | grep 'main('
    at demo.MathGame.main(MathGame.java:17)

5、jad 命令

通过 jad 来反编译 Main Class

[arthas@21948]$ jad demo.MathGame

ClassLoader:
+-sun.misc.Launcher$AppClassLoader@55f96302
  +-sun.misc.Launcher$ExtClassLoader@74a14482

Location:
/C:/Users/scy/Desktop/arthas/math-game.jar

       /*
        * Decompiled with CFR.
        */
       package demo;

       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();
           private int illegalArgumentCount = 0;

           public static void main(String[] args) throws InterruptedException {
    
    
               MathGame game = new MathGame();
               while (true) {
    
    
/*16*/             game.run();
/*17*/             TimeUnit.SECONDS.sleep(1L);
               }
           }

           public void run() throws InterruptedException {
    
    
               try {
    
    
/*23*/             int number = random.nextInt() / 10000;
/*24*/             List<Integer> primeFactors = this.primeFactors(number);
/*25*/             MathGame.print(number, primeFactors);
               }
               catch (Exception e) {
    
    
/*28*/             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 + "=");
/*34*/         for (int factor : primeFactors) {
    
    
/*35*/             sb.append(factor).append('*');
               }
/*37*/         if (sb.charAt(sb.length() - 1) == '*') {
    
    
/*38*/             sb.deleteCharAt(sb.length() - 1);
               }
/*40*/         System.out.println(sb);
           }

           public List<Integer> primeFactors(int number) {
    
    
/*44*/         if (number < 2) {
    
    
/*45*/             ++this.illegalArgumentCount;
                   throw new IllegalArgumentException("number is: " + number + ", need >= 2");
               }
               ArrayList<Integer> result = new ArrayList<Integer>();
/*50*/         int i = 2;
/*51*/         while (i <= number) {
    
    
/*52*/             if (number % i == 0) {
    
    
/*53*/                 result.add(i);
/*54*/                 number /= i;
/*55*/                 i = 2;
                       continue;
                   }
/*57*/             ++i;
               }
/*61*/         return result;
           }
       }

Affect(row-cnt:1) cost in 432 ms.
[arthas@21948]$

6、watch 命令

通过watch命令来查看demo.MathGame#primeFactors函数的返回值:

[arthas@21948]$ watch demo.MathGame primeFactors returnObj
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 66 ms, listenerId: 1
method=demo.MathGame.primeFactors location=AtExit
ts=2023-06-21 16:43:40; [cost=0.7314ms] result=@ArrayList[
    @Integer[2],
    @Integer[7],
    @Integer[13159],
]
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2023-06-21 16:43:41; [cost=0.1341ms] result=null
method=demo.MathGame.primeFactors location=AtExit
ts=2023-06-21 16:43:42; [cost=0.4295ms] result=@ArrayList[
    @Integer[3],
    @Integer[14197],
]

更多的功能可以查看进阶使用:https://arthas.aliyun.com/doc/advanced-use.html

01、查看某个方法的参数、返回值、抛出的异常。

watch 全类名 方法名 returnObj // 查看方法的返回值

watch 全类名 方法名 '{params, throwExp}' -e // 查看参数和异常,方法名支持 通配符 *,-e表示只捕获抛出异常时的请求,后面还以跟 -x 2,-x表示“对象层级”。

02、设置输出json格式。

options json-format true //设置以json格式输出。

7、退出 arthas

如果只是退出当前的连接,可以用quit或者exit命令。Attach 到目标进程上的 arthas 还会继续运行,端口会保持开放,下次连接时可以直接连接上。

如果想完全退出 arthas,可以执行stop命令。

8、命令总汇

1)help:查看所有可用的 Arthas 命令和说明。

2)jvm:查看当前 JVM 的相关信息,包括堆大小、GC 策略、线程数等。

3)classloader:查看和操作类加载器信息,包括已加载的类、类加载器层级等。

4)thread(cpu占用过高/死锁):查看和操作线程状态和堆栈信息,包括线程数量、状态、阻塞信息等。

5)trace(方法耗时及跟踪 ):跟踪指定方法的执行情况,输出方法参数、返回值、耗时等信息。

6)watch(查看函数的参数/返回值/异常信息):监控指定方法的执行情况,当指定条件满足时自动触发相应的操作。

7)sc:查看和操作 Spring 上下文信息,包括 Bean 定义、Bean 生命周期等。

8)sql:查看和操作数据库连接和 SQL 执行情况,支持常见的 JDBC 驱动程序。

9)dashboard(内存泄漏):启动 Arthas 的可视化界面,展示当前应用程序的各种运行情况。

10) jad:反编译源代码

11)tt:

  • 发现异常并查看异常 tt -t com.UserServiceImpl check //记录方法调用信息

    tt -i 1001 //上面指令发现异常后,查看异常

    tt -i 1001 -p //重新调用,重现异常

  • 查看、更新类成员变量值

    ognl '@com.Arthas@hashSet' //查看

    ognl ‘@[email protected](“test”)’ //更新

四、参考

JVM调优神器,运用 Arthas 释放 Java应用性能的全部潜力
https://juejin.cn/post/7234545968094773307

Arthas
https://blog.csdn.net/weixin_42061487/article/details/120520260

ARTHAS进阶学习(常用命令)
https://www.cnblogs.com/theRhyme/p/10659265.html

猜你喜欢

转载自blog.csdn.net/qq_25775675/article/details/107923477