Arthas基本使用

1. Arthas下载安装

Arthas官网

  • Windows/Mac 输入cmd按回车后进入想要下载的目录执行命令curl -O https://arthas.aliyun.com/arthas-boot.jar

  • Linux

    进入想要下载的目录执行命令wget https://arthas.aliyun.com/arthas-boot.jar 启动arthas命令:java -jar arthas-boot.jar

    2. Arthas使用命令

第一招:Watch命令

watche命令有很多参数,用于控制观察的时机。例如-b(before)函数调用前,-e(exception)异常函数后,-s函数返回后, -f(finish) 函数结束后-n(number)是打印的次数,超过该次数就会自动结束监听。

{params,returnObj,throwExp}

  • params 执行该方法的入参,该入参显示可以是方法执行前和执行后,-b 和 -s控制
  • returnObj 执行该方法后返回的结果
  • throwExp 执行该方法是否有异常,如果有的话就会输出异常信息
  • @Thread@currentThread().getName(),查看执行该方法的线程名字
-x 是用于显示对象的嵌套层数 最大为4层
例如结构如下
    static class Student{
        private String className;
        private List<String> address;
    }
    static class Person {
        private String name;
        private Student stu;
    }

-x 3 显示结果
result=@ArrayList[
    @Object[][
        @String[h],
    ],
    @ArthasController[
    ],
    @ArrayList[
        @Person[
            name=@String["hhh"],
            stu=@Student[com.dev.wizard.springboot.arthas.ArthasController$Student@fad42d0],
        ],
    ],
]
-x 1 显示结果
result=@ArrayList[
    @Object[][isEmpty=false;size=1],
    @ArthasController[com.dev.wizard.springboot.arthas.ArthasController@3280fe86],
    @ArrayList[isEmpty=false;size=1],
]


-b 是用于观察进入某个方法前参数的情况

例如如下的结构
List<String> list = new ArrayList<>();
        list.add("test1");
        list.add("test2");
String value = "ABC";
  private String methodChangeParam(String value, List<String> list){
        list.add("test0");
        return value + "DDDDD";
    }

不带-b的命令观察结果
    入参是有test0的所以是执行了该方法后的结果因为该方法内改变了入参的数据
    Affect(class count: 1 , method count: 1) cost in 109 ms, listenerId: 1
method=com.dev.wizard.springboot.arthas.ArthasController.methodChangeParam location=AtExit
ts=2022-09-01 10:12:43; [cost=0.7164ms] result=@ArrayList[
    @Object[][
        @String[ABC],
        @ArrayList[
            @String[test1],
            @String[test2],
            @String[test0],   <---
        ],
    ],
    @String[ABCDDDDD],
    null,
]
-b的命令观察结果
    入参没有test0的是指方法执行前就讲所有的入参进行了打印
    Affect(class count: 1 , method count: 1) cost in 47 ms, listenerId: 2
method=com.dev.wizard.springboot.arthas.ArthasController.methodChangeParam location=AtEnter
ts=2022-09-01 10:20:46; [cost=0.0112ms] result=@ArrayList[
    @Object[][
        @String[ABC],
        @ArrayList[
            @String[test1],
            @String[test2],
        ],
    ],
    null,
    null,
]
使用 -s  -b同时观察方法调用前后的参数
  watch com.dev.wizard.springboot.arthas.ArthasController methodChangeParam '{params,returnObj,throwExp}'  -n 5  -x 3 -s -b

method=com.dev.wizard.springboot.arthas.ArthasController.methodChangeParam location=AtEnter
ts=2022-09-01 11:13:43; [cost=0.091ms] result=@ArrayList[
    @Object[][
        @String[ABC],
        @ArrayList[
            @String[test1],
            @String[test2],
        ],
    ],
    null,
    null,
]
method=com.dev.wizard.springboot.arthas.ArthasController.methodChangeParam location=AtExit
ts=2022-09-01 11:13:43; [cost=4.063598082349E8ms] result=@ArrayList[
    @Object[][
        @String[ABC],
        @ArrayList[
            @String[test1],
            @String[test2],
            @String[test0],
        ],
    ],
    @String[ABCDDDDD],
    null,
]



-e表示当被观察的方法抛出异常时才会打印监听的参数 如果没有异常没有任何输出
例如下述的方法
    private String methodWithException(int number){
        int value = number / 0;
        return "" + value;
    }


watch com.dev.wizard.springboot.arthas.ArthasController methodWithException '{params,returnObj,throwExp}'  -n 5  -x 3 -e

method=com.dev.wizard.springboot.arthas.ArthasController.methodChangeParam location=AtExceptionExit
ts=2022-09-01 10:10:37; [cost=0.1383ms] result=@ArrayList[
    @Object[][
        @String[ABC],
        @ArrayList[
            @String[test1],
            @String[test2],
        ],
    ],
    null,
    java.lang.UnsupportedOperationException
        at java.util.AbstractList.add(AbstractList.java:148)
        at java.util.AbstractList.add(AbstractList.java:108)
        at com.dev.wizard.springboot.arthas.ArthasController.methodChangeParam(ArthasController.java:31)
        at com.dev.wizard.springboot.arthas.ArthasController.getResult(ArthasController.java:20)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
    ....
   ]

第二招:带过滤的Watch命令

public String getResult(@RequestParam("method") String method, @RequestParam("type") String type){
        String value = type;
        List<String> list = new ArrayList<>();
        list.add("test1");
        list.add("test2");
        this.methodChangeParam(value, list);


watch com.dev.wizard.springboot.arthas.ArthasController methodChangeParam '{params,returnObj,throwExp}' "params[0].equals('ABC') && params[1].get(0).equals('ABC')"  -n 5  -x 3


使用grep命令后的关键字是对大小写敏感的 并且只会返回存在关键字的参数 例如params中存在只返回params这一项
watch com.dev.wizard.springboot.arthas.ArthasController methodChangeParam '{params,returnObj,throwExp}' -n 5 -x 3| grep AB


查看执行该方法的线程名字
watch com.dev.wizard.springboot.arthas.ArthasController methodChangeParam '{params,returnObj,throwExp,@Thread@currentThread().getName()}' -n 5 -x 3

Affect(class count: 1 , method count: 1) cost in 47 ms, listenerId: 6
method=com.dev.wizard.springboot.arthas.ArthasController.methodChangeParam location=AtExit
ts=2022-09-01 19:58:16; [cost=0.1034ms] result=@ArrayList[
    @Object[][
        @String[ZZ],
        @ArrayList[
            @String[ZZ],
            @String[test1],
            @String[test2],
            @String[test0],
        ],
    ],
    @String[ZZDDDDD],
    null,
    @String[http-nio-80-exec-5],   <======
]

第三招:Trace 命令


   private String methodWithException(int number){
        System.out.println("hello");
        int num = 3 + 5;
        int value = number / 0;
        return "" + value;
    }

在使用如下命令trace上述的方法时候显示如下日志
trace com.dev.wizard.springboot.arthas.ArthasController methodWithException  -n 5 --skipJDKMethod false

`---ts=2022-09-01 20:13:07;thread_name=http-nio-80-exec-1;id=26;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@74e6094b
    `---[0.8582ms] com.dev.wizard.springboot.arthas.ArthasController:methodWithException() [throws Exception]
        +---[13.25% 0.1137ms ] java.io.PrintStream:println() #38
        `---throw:java.lang.ArithmeticException #40 [/ by zero]

3. Arthas插件神器

image-20220909202238579

image-20220909202238579