Java工具arthas的使用--结合实际工作
Posted master-dragon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java工具arthas的使用--结合实际工作相关的知识,希望对你有一定的参考价值。
目录
安装使用
https://arthas.aliyun.com/zh-cn/
- help命令帮助
- cls命令清屏
- 命令列表:https://arthas.aliyun.com/doc/commands.html
sc 查看JVM已加载的类信息
“Search-Class” 的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,这个命令支持的参数有 [d]、[E]、[f] 和 [x:]。
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
[d] | 输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。如果一个类被多个ClassLoader所加载,则会出现多次 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[f] | 输出当前类的成员变量信息(需要配合参数-d一起使用) |
[x:] | 指定输出静态变量时属性的遍历深度,默认为 0,即直接使用 toString 输出 |
[c:] | 指定class的 ClassLoader 的 hashcode |
[classLoaderClass:] | 指定执行表达式的 ClassLoader 的 class name |
[n:] | 具有详细信息的匹配类的最大数量(默认为100) |
sm(查看已加载类的方法信息)
“Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。
sm 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到。
参数
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
[d] 展示每个方法的详细信息
[E] 开启正则表达式匹配,默认为通配符匹配
[c:] 指定class的 ClassLoader 的 hashcode
[classLoaderClass:] 指定执行表达式的 ClassLoader 的 class name
[n:] 具有详细信息的匹配类的最大数量(默认为100)
thread命令
查看所有线程
dashboard命令
thread
, memory
, gc
, runtime
相关信息
trace
方法内部调用路径,并输出方法路径上的每个节点上耗时;
* trace 能方便的帮助你定位和发现因 RT 高而导致的性能问题缺陷,但其每次只能跟踪一级方法的调用链路; 3.3.0 版本后,可以使用动态Trace功能,不断增加新的匹配类
* 如果方法调用的次数很多,那么可以用-n参数指定捕捉结果的次数
* --skipJDKMethod : skip jdk method trace, default value true.
* 使用 --exclude-class-pattern 参数可以排除掉指定的类
多层调用trace
附代码
@GetMapping(value = "/test-cost")
public String getTestCost()
return cost1s();
private String cost1s()
try
TimeUnit.SECONDS.sleep(1);
catch (Exception e)
return cost2s();
private String cost2s()
try
TimeUnit.SECONDS.sleep(2);
catch (Exception e)
return cost3s();
private String cost3s()
try
TimeUnit.SECONDS.sleep(3);
catch (Exception e)
return "3s";
特定调用参数trace
eg: trace如下方法
- trace id = 2 的调用
trace com.example.demo.control.TestControl getTestParam "params[0]=2"
- trace id > 129 的调用
trace com.example.demo.control.TestControl getTestParam "params[0]>129"
- trace id > 129 && id < 133 的调用
trace com.example.demo.control.TestControl getTestParam "params[0]>129 && params[0]<133"
- trace id > 129 && name="aa"的调用
trace com.example.demo.control.TestControl getTestParam "params[0]>129 && params[1].equals('aa')"
多方法&多层调用
附代码
@GetMapping(value = "/test-cost")
public Integer getTestCost()
int a = cost1();
int b = cost2();
int c = cost3();
return a + b + c;
private Integer cost1()
try
TimeUnit.MILLISECONDS.sleep(100);
catch (Exception e)
return 100 + cost11();
private Integer cost2()
try
TimeUnit.MILLISECONDS.sleep(200);
catch (Exception e)
return 200 + cost22();
private Integer cost3()
try
TimeUnit.MILLISECONDS.sleep(300);
catch (Exception e)
return 300;
private Integer cost11()
try
TimeUnit.MILLISECONDS.sleep(50);
catch (Exception e)
return 50;
private Integer cost22()
try
TimeUnit.MILLISECONDS.sleep(30);
catch (Exception e)
return 30;
stack
- 输出当前方法被调用的调用路径
很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。
[arthas@14273]$ stack com.example.demoapi.control.TestControl cost11
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 45 ms, listenerId: 4
ts=2021-03-27 12:25:34;thread_name=http-nio-8080-exec-5;id=17;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@11bd803
@com.example.demoapi.control.TestControl.cost11()
at com.example.demoapi.control.TestControl.cost1(TestControl.java:35)
at com.example.demoapi.control.TestControl.getTestCost(TestControl.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2)
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:189)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
watch
方法执行数据观测: 让你能方便的观察到指定方法的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。
-
watch 命令定义了4个观察事件点,即 -b 方法调用前,-e 方法异常后,-s 方法返回后,-f 方法结束后
-
4个观察事件点 -b、-e、-s 默认关闭,-f 默认打开,当指定观察点被打开后,在相应事件点会对观察表达式进行求值并输出
-
这里要注意方法入参和方法出参的区别,有可能在中间被修改导致前后不一致,除了 -b 事件点 params 代表方法入参外,其余事件都代表方法出参
-
当使用 -b 时,由于观察事件点是在方法调用前,此时返回值或异常均不存在
-
watch com.example.demoapi.control.UserControl getById "params,returnObj" -x 2
-
只观察方法入参
watch com.example.demoapi.control.UserControl getById "params,returnObj" -b
ognl
学习文档:https://arthas.aliyun.com/doc/ognl.html
- 获取静态变量
[arthas@31512]$ ognl '@com.example.demoapi.control.TestControl@CNT'
@Integer[1024]
- 执行多个表达式,并对结果对象进行展开
[arthas@31195]$ ognl '#value1=@com.example.demoapi.util.SpringContextUtils@getBean("testControl"),#value1.ognlTest("hello")' -x 1
@ArrayList[
@ResponseData[com.example.demoapi.ResponseData@5b061dae],
@ResponseData[com.example.demoapi.ResponseData@699479c4],
@ResponseData[com.example.demoapi.ResponseData@56997e18],
]
[arthas@31195]$ ognl '#value1=@com.example.demoapi.util.SpringContextUtils@getBean("testControl"),#value1.ognlTest("hello")' -x 2
@ArrayList[
@ResponseData[
code=@String[[12]深入浅出工作开源框架Camunda: 使用Arthas监控Camunda
Arthas(阿尔萨斯)-java诊断工具-----来源于网络