前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线上 JVM 调优工具 Athars 入门

线上 JVM 调优工具 Athars 入门

作者头像
用户3587585
发布2024-04-17 17:58:38
1030
发布2024-04-17 17:58:38
举报
文章被收录于专栏:阿福谈Web编程阿福谈Web编程
1 Athas 简介

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

1.1 背景

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

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

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

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

1.2 Arthas 能为你做什么?

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

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

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

Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

2 快速入门
2.1 启动 math-game
代码语言:javascript
复制
# 登录linux 服务器,执行下载math-game.jar并运行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.2 启动 arthas

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

代码语言:javascript
复制
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
  • 执行该程序的用户需要和目标进程具有相同的权限。比如以admin用户来执行:sudo su admin && java -jar arthas-boot.jarsudo -u admin -EH java -jar arthas-boot.jar
  • 如果 attach 不上目标进程,可以查看~/logs/arthas/ 目录下的日志。
  • 如果下载速度比较慢,可以使用 aliyun 的镜像:java -jar arthas-boot.jar --repo-mirror aliyun --use-http
  • java -jar arthas-boot.jar -h 打印更多参数信息。

启动 arthas-boot 程序后控制台会出现了如下日志信息:

代码语言:javascript
复制
[root@iZf8zdh51orpja1xwy1mutZ local]# java -jar arthas-boot.jar
[INFO] JAVA_HOME: /usr/local/jdk1.8.0_381/jre
[INFO] arthas-boot version: 3.7.2
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 445171 /usr/local/nacos/target/nacos-server.jar
  [2]: 436414 math-game.jar

进程 1 是nacosmath-game进程是第 2 个,则输入 2,再输入回车/enter。Arthas 会 attach 到目标进程上,并输出日志:

选择应用 java 进程:

代码语言:javascript
复制
[INFO] Start download arthas from remote server: https://arthas.aliyun.com/download/3.7.2?mirror=aliyun
[INFO] Download arthas success.
[INFO] arthas home: /root/.arthas/lib/3.7.2/arthas
[INFO] Try to attach process 436414
[INFO] Attach process 436414 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.7.2                                                                
main_class                                                                      
pid        436414                                                               
time       2024-04-12 00:04:18      
2.3 查看 dashboard

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

代码语言:javascript
复制
[arthas@436414]$ dashboard
ID   NAME                         GROUP         PRIORITY  STATE    %CPU      DELTA_TI TIME      INTERRUP DAEMON    
-1   C2 CompilerThread0           -             -1        -        0.0       0.000    0:0.331   false    true      
-1   C1 CompilerThread1           -             -1        -        0.0       0.000    0:0.299   false    true      
1    main                         main          5         TIMED_WA 0.0       0.000    0:0.139   false    false     
-1   VM Periodic Task Thread      -             -1        -        0.0       0.000    0:0.112   false    true      
19   arthas-NettyHttpTelnetBootst system        5         RUNNABLE 0.0       0.000    0:0.062   false    true      
-1   GC task thread#0 (ParallelGC -             -1        -        0.0       0.000    0:0.046   false    true      
-1   GC task thread#1 (ParallelGC -             -1        -        0.0       0.000    0:0.038   false    true      
-1   VM Thread                    -             -1        -        0.0       0.000    0:0.032   false    true      
13   arthas-NettyHttpTelnetBootst system        5         RUNNABLE 0.0       0.000    0:0.017   false    true      
8    Attach Listener              system        9         RUNNABLE 0.0       0.000    0:0.012   false    true      
Memory                   used    total   max      usage   GC                                                       
heap                     20M     72M     796M     2.53%   gc.ps_scavenge.count         5                           
ps_eden_space            1M      29M     286M     0.69%   gc.ps_scavenge.time(ms)      33                          
ps_survivor_space        0K      2048K   2048K    0.00%   gc.ps_marksweep.count        1                           
ps_old_gen               18M     41M     597M     3.05%   gc.ps_marksweep.time(ms)     38                          
nonheap                  27M     28M     -1       97.10%                                                           
code_cache               4M      4M      240M     1.88%                                                            
metaspace                20M     21M     -1       96.67%                                                           
Runtime                                                                                                            
os.name                                                   Linux                                                    
os.version                                                5.10.134-16.1.al8.x86_64
2.4 通过 thread 命令获取线程堆栈信息
代码语言:javascript
复制
[arthas@629401]$ thread
Threads Total: 21, NEW: 0, RUNNABLE: 7, BLOCKED: 0, WAITING: 3, TIMED_WAITING: 4, TERMINATED: 0, Internal threads: 
7                                                                                                                  
ID   NAME                         GROUP         PRIORITY  STATE    %CPU      DELTA_TI TIME      INTERRUP DAEMON    
20   arthas-command-execute       system        5         RUNNABLE 0.25      0.000    0:0.002   false    true      
12   Keep-Alive-Timer             system        8         TIMED_WA 0.08      0.000    0:0.000   false    true      
-1   VM Thread                    -             -1        -        0.05      0.000    0:0.025   false    true      
-1   VM Periodic Task Thread      -             -1        -        0.03      0.000    0:0.014   false    true      
2    Reference Handler            system        10        WAITING  0.0       0.000    0:0.001   false    true      
3    Finalizer                    system        8         WAITING  0.0       0.000    0:0.002   false    true      
4    Signal Dispatcher            system        9         RUNNABLE 0.0       0.000    0:0.000   false    true      
8    Attach Listener              system        9         RUNNABLE 0.0       0.000    0:0.011   false    true      
10   arthas-timer                 system        9         WAITING  0.0       0.000    0:0.000   false    true      
13   arthas-NettyHttpTelnetBootst system        5         RUNNABLE 0.0       0.000    0:0.018   false    true      
14   arthas-NettyWebsocketTtyBoot system        5         RUNNABLE 0.0       0.000    0:0.001   false    true      
15   arthas-NettyWebsocketTtyBoot system        5         RUNNABLE 0.0       0.000    0:0.001   false    true      
16   arthas-shell-server          system        9         TIMED_WA 0.0       0.000    0:0.000   false    true      
17   arthas-session-manager       system        9         TIMED_WA 0.0       0.000    0:0.000   false    true      
19   arthas-NettyHttpTelnetBootst system        5         RUNNABLE 0.0       0.000    0:0.055   false    true      
1    main                         main          5         TIMED_WA 0.0       0.000    0:0.066   false    false     
-1   GC task thread#1 (ParallelGC -             -1        -        0.0       0.000    0:0.040   false    true      
-1   C1 CompilerThread1           -             -1        -        0.0       0.000    0:0.268   false    true      
-1   GC task thread#0 (ParallelGC -             -1        -        0.0       0.000    0:0.040   false    true      
-1   C2 CompilerThread0           -             -1        -        0.0       0.000    0:0.326   false    true      

第1行表示总共有21个线程,其中:RUNNABLE 状态的线程7个、WAITING 状态的线程3个、TIMED_WAITING状态的线程4个,JVM内部线程7个。线程ID为-1的均为JVM内部线程。

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

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

代码语言:javascript
复制
[arthas@533211]$ thread 1 | grep 'main('
    at demo.MathGame.main(MathGame.java:17)
2.6 通过 jad 来反编译 Main Class
代码语言:javascript
复制
$ 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.
2.7 退出 arthas

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

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

3 命令列表
3.1 jvm 相关命令
  • dashboard:当前系统的实时数据面板
  • getstatics: 查看类的静态属性
  • heapdump: dump java heap, 类似 jmap 命令的 heap dump 功能
  • jvm: 查看当前 JVM 的信息
  • logger: 查看和修改 logger
  • mbean: 查看 Mbean 的信息
  • memory: 查看 JVM 的内存信息
  • ognl: 执行 ognl 表达式
  • perfcounter: 查看当前 JVM 的 Perf Counter 信息
  • sysenv: 查看 JVM 的环境变量
  • sysprop: 查看和修改 JVM 的系统属性
  • thread: 查看当前 JVM 的线程堆栈信息
  • vmoption: 查看和修改 JVM 里诊断相关的 option
  • vmtool: 从 jvm 里查询对象,执行 forceGc
3.2 class/classloader 相关
  • classloader: 查看 classloader 的继承树,urls,类加载信息,使用 classloader 去 getResource
  • dump: dump 已加载类的 byte code 到特定目录
  • jad: 反编译指定已加载类的源码
  • mc: 内存编译器,内存编译.java文件为.class文件
  • redefine: 加载外部的.class文件,redefine 到 JVM 里
  • retransform: 加载外部的.class文件,retransform 到 JVM 里
  • sc: 查看 JVM 已加载的类信息
  • sm: 查看已加载类的方法信息
3.3 monitor/watch/trace 相关

注意请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 `stop` 或将增强过的类执行 `reset` 命令。

  • monitor: 方法执行监控
  • stack: 输出当前方法被调用的调用路径
  • trace: 方法内部调用路径,并输出方法路径上的每个节点上耗时
  • tt:方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
  • watch: 方法执行数据观测
3.4 profiler/火焰图

profiler: 使用async-profiler对应用采样,生成火焰图

jfr: 动态开启关闭JFR记录

3.5 鉴权
  • auth: 鉴权
3.6 options
  • options: 查看或设置 Arthas 全局开关
3.7 管道

当线上出现偶发的问题,比如需要 watch 某个条件,而这个条件一天可能才会出现一次时,异步后台任务就派上用场了,详情请参考:https://arthas.gitee.io/doc/async.html

  • 使用 > 将结果重写向到日志文件,使用 & 指定命令是后台运行,session 断开不影响任务执行(生命周期默认为 1 天)
  • jobs: 列出所有 job
  • kill - 强制终止任务
  • fg - 将暂停的任务拉到前台执行
  • bg - 将暂停的任务放到后台执行
4 基础命令
  • base64: base64 编码转换,和 linux 里的 base64 命令类似
  • cat: 打印文件内容,和 linux 里的 cat 命令类似
  • cls: 清空当前屏幕区域
  • echo: 打印参数,和 linux 里的 echo 命令类似
  • grep: 匹配查找,和 linux 里的 grep 命令类似
  • help: 查看命令帮助信息
  • history: 打印命令历史
  • keymap: Arthas 快捷键列表及自定义快捷键
  • pwd: 返回当前的工作目录,和 linux 命令类似
  • quit: 退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
  • reset: 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
  • session: 查看当前会话的信息
  • stop: 关闭 Arthas 服务端,所有 Arthas 客户端全部退出
  • tee: 复制标准输入到标准输出和指定的文件,和 linux 里的 tee 命令类似
  • version: 输出当前目标 Java 进程所加载的 Arthas 版本号
小结

本文主要介绍了来自阿里的开源线上监控诊断工具 Arthas 的下载安装,并在Linux服务器中使用Arthas对 Java应用进行了dashboard 查看控制面板数据 和 thread 命令查看监控进程中的线程堆栈信息,以及jad反编译命令的用法。然后简要介绍了Arthas 的命令列表,但是想要搞明白具体每个命令的用法和使用时的参数,请移步Arthas官网命令列表页 https://arthas.gitee.io/doc/commands.html

点击每个命令处的链接即可跳转到每个命令的用法详情页。

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-12,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 阿福谈Web编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1 背景
  • 1.2 Arthas 能为你做什么?
  • 2 快速入门
    • 2.1 启动 math-game
      • 2.2 启动 arthas
        • 2.3 查看 dashboard
          • 2.4 通过 thread 命令获取线程堆栈信息
            • 2.5 通过 thread 命令来获取到math-game进程的 Main Class
              • 2.6 通过 jad 来反编译 Main Class
                • 2.7 退出 arthas
                • 3 命令列表
                  • 3.1 jvm 相关命令
                    • 3.2 class/classloader 相关
                      • 3.3 monitor/watch/trace 相关
                        • 3.4 profiler/火焰图
                          • 3.5 鉴权
                            • 3.6 options
                              • 3.7 管道
                              • 4 基础命令
                              • 小结
                              相关产品与服务
                              远程调试
                              远程调试(Remote Debugging,RD)在云端为用户提供上千台真实手机/定制机/模拟器设备,快速实现随时随地测试。运用云测技术对测试方式、操作体验进行了优化,具备多样性的测试能力,包括随时截图和记录调试日志,稳定的支持自动化测试, 设备灵活调度,用例高效执行, 快速定位产品功能和兼容性问题。云手机帮助应用、移动游戏快速发现和解决问题,节省百万硬件费用,加速敏捷研发流程。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                              http://www.vxiaotou.com