飞道的博客

Java线上诊断工具Arthas

353人阅读  评论(0)
  • 概述
    Arthas是一个开源的线上诊断工具,可以实时查看线上代码运行情况,详情参考Arthas

  • 安装
    1.下载jar包即可 https://alibaba.github.io/arthas/arthas-boot.jar
    2.以jar的允许方式就可以了

    java -jar arthas-boot.jar  进程id(可使用jps列出所有jvm进程)
    

  • 命令列表

  • jad命令(获取已加载类的源码)

    //主要用来看已经加载了类的源码,一般用于动态加载的class的源码比较方便
    [arthas@773]$ jad com/example/jvm/Hello
    
    ClassLoader:
    +-sun.misc.Launcher$AppClassLoader@18b4aac2
      +-sun.misc.Launcher$ExtClassLoader@362d9542
    
    Location:
    /Users/wuxinxin/IdeaProjects/javaseTest/target/classes/
    
    /*
     * Decompiled with CFR.
     */
    package com.example.jvm;
    
    import java.io.IOException;
    
    public class Hello {
        public static void main(String[] args) throws IOException {
            System.out.println("Hello, World");
            System.in.read();
        }
    }
    
    Affect(row-cnt:1) cost in 354 ms.
    
  • ognl(查看静态变量值)

    [arthas@909]$ ognl @com.example.jvm.Hello@list.size()
    @Integer[2]
    [arthas@909]$
    [arthas@909]$ ognl @com.example.jvm.Hello@list
    @ArrayList[
        @String[aa],
        @String[cc],
    ]
    
  • trace(跟踪指定方法的执行耗时情况)

    说明:可以很好的跟踪线上运行耗时情况,打印线上实时的执行耗时情况

  • watch(查看某方法的参数列表和结果)
    语法:watch 类全路径名 方法名称 ‘{入参对象(Object数组params)和Object结果对象returnObj}’

    [arthas@1359]$ watch  com.example.jvm.arthas.UserService delUser '{params,returnObj.toString()}'
    Press Q or Ctrl+C to abort.
    Affect(class-cnt:1 , method-cnt:1) cost in 43 ms.
    ts=2020-05-24 16:29:53; [cost=1.942564ms] result=@ArrayList[
        @Object[][isEmpty=false;size=1],
        @String[[liujing, wxx2222, wxx3333]],
    ]
    [arthas@1359]$ watch  com.example.jvm.arthas.UserService checkUser '{params,returnObj.toString()}'
    Press Q or Ctrl+C to abort.
    Affect(class-cnt:1 , method-cnt:1) cost in 12 ms.
    ts=2020-05-24 16:30:53; [cost=0.151088ms] result=@ArrayList[
        @Object[][isEmpty=false;size=1],
        @String[0],
    ]
    [arthas@1359]$ watch  com.example.jvm.arthas.UserService checkUser '{params[0],returnObj.toString()}'
    Press Q or Ctrl+C to abort.
    Affect(class-cnt:1 , method-cnt:1) cost in 9 ms.
    ts=2020-05-24 16:31:53; [cost=0.125463ms] result=@ArrayList[
        @Integer[0],
        @String[0],
    ]
    
  • stack(查看运行时某方法的调用栈)

    [arthas@1415]$ stack com.example.jvm.arthas.UserService checkUser
    Press Q or Ctrl+C to abort.
    Affect(class-cnt:1 , method-cnt:1) cost in 43 ms.
    ts=2020-05-24 16:58:49;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2
        @com.example.jvm.arthas.UserService.checkUser()
            at com.example.jvm.arthas.UserService.delUser(UserService.java:58)
            at com.example.jvm.arthas.ArthasTest.main(ArthasTest.java:39)
    
  • tt命令(又称为时空隧道,就是可以记录当时调用情况,并且可以重复执行)

    //tt -t 类路径名称 方法名称(命令执行那一刻,会记录这个方法的所有执行记录)
    [arthas@1642]$ tt -t  com.example.jvm.arthas.UserService delUser
    Press Q or Ctrl+C to abort.
    Affect(class-cnt:1 , method-cnt:1) cost in 42 ms.
     INDEX   TIMESTAMP          COST(ms)  IS-RE  IS-EXP  OBJECT        CLASS                        METHOD
                                          T
    ----------------------------------------------------------------------------------------------------------------------------
     1000    2020-05-24 17:35:  2.019116  true   false   0x5fd0d5ae    UserService                  delUser
             05
    //tt -i index 可以查看某个记录详情,甚至可以看到入参和返回值
    [arthas@1642]$ tt -i 1000
     INDEX          1000
     GMT-CREATE     2020-05-24 17:35:05
     COST(ms)       2.019116
     OBJECT         0x5fd0d5ae
     CLASS          com.example.jvm.arthas.UserService
     METHOD         delUser
     IS-RETURN      true
     IS-EXCEPTION   false
     PARAMETERS[0]  @Integer[0]
     RETURN-OBJ     @ArrayList[
                        @String[liujing],
                        @String[wxx2222],
                        @String[wxx3333],
                    ]
    Affect(row-cnt:1) cost in 6 ms.
    
    //tt -i index -p可以在当时条件下,再重复调用(慎用,发生真实调用)
    [arthas@1642]$ tt -i 1000 -p
     RE-INDEX       1000
     GMT-REPLAY     2020-05-24 17:40:35
     OBJECT         0x5fd0d5ae
     CLASS          com.example.jvm.arthas.UserService
     METHOD         delUser
     PARAMETERS[0]  @Integer[0]
     IS-RETURN      true
     IS-EXCEPTION   false
     COST(ms)       0.674845
     RETURN-OBJ     @ArrayList[
                        @String[wxx2222],
                        @String[wxx3333],
                    ]
    Time fragment[1000] successfully replayed 1 times.
    
  • thread命令(查看线程状态)

    [arthas@1642]$ thread
    //这里展示当前jvm进程的所有线程情况,有几个比较重要的字段需要关注
    //1.name 是线程的名称
    //2.state表示线程状态
        a.BLOCKED 一般使用了 synchronized的锁等待
        b.WAITING 一般是无限等待,需要唤醒 park(reentrantLock.lock()内部是park方式实现,这种锁等待也是这种状态)
        c.TIMED_WAITI 一般是指有时间的等待,自动唤醒(sleep,LockSupport.parkNanos)
    //3.cpu ,如果有cpu飙高情况,可以看看哪个线程导致
    //4.thread id 可以看具体线程情况,比如WAITING是在哪里等待,都能看到
    
    


    syn关键字方式加锁状态详情

    //BLOCKED状态测试,没抢到锁的是BLOCKED,抢到锁的但是sleep为TIMED_WAI
     public static void main(String[] args) throws Exception {
    
            ArthasTest arthasTest = new ArthasTest();
           //测试锁的情况
    
            for(int i=0;i<10;i++){
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        arthasTest.lock1();
                    }
                });
    
                thread.setName("wxx"+i+"线程");
    
                thread.start();
            }
    
            System.in.read();
        }
        
        public synchronized void lock1(){
    
        try {
            Thread.sleep(60000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    
    }
    


    lock方式加锁状态

     public static void main(String[] args) throws Exception {
    
            ArthasTest arthasTest = new ArthasTest();
    
            ReentrantLock reentrantLock=new ReentrantLock();
    
            for(int i=0;i<10;i++){
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        arthasTest.lock1(reentrantLock);
                    }
                });
    
                thread.setName("wxx"+i+"线程");
    
                thread.start();
            }
    
            System.in.read();
        }
    
    public  void lock1(ReentrantLock reentrantLock){
    
            reentrantLock.lock();
            try {
                Thread.sleep(60000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            reentrantLock.unlock();
        }
    

  • 总结
    1.可以查看线上实时情况,比如cpu飙高,哪个线程,哪行代码
    2.校验允许结果和预期结果,查看stack, 入参和结果
    3.运行时动态加载编译的class,可以直接查看源码
    4.接口执行很慢,可以实时查看接口调用栈的耗时详情


转载:https://blog.csdn.net/weixin_38312719/article/details/106313175
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场