1. 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插件神器
PREVIOUSIDEA集成Jrebel实现热部署