Java工具arthas的使用--结合实际工作

安装使用

https://arthas.aliyun.com/zh-cn/
在这里插入图片描述

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 '#[email protected]@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 '#[email protected]@getBean("testControl"),#value1.ognlTest("hello")' -x 2
@ArrayList[
    @ResponseData[
        code=@String[0],
        msg=@String[SUCCESS],
        data=@String[what:hello],
    ],
    @ResponseData[
        code=@String[0],
        msg=@String[SUCCESS],
        data=@String[why:hello],
    ],
    @ResponseData[
        code=@String[0],
        msg=@String[SUCCESS],
        data=@String[how:hello],
    ],
]
  • 指定ClassLoader的hashcode
[arthas@31512]$ classloader -t
+-BootstrapClassLoader
+-org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@4f0cab0a
+-org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@37045b48
+-sun.misc.Launcher$ExtClassLoader@16f65612
  +-com.taobao.arthas.agent.ArthasClassloader@daedcf4
  +-sun.misc.Launcher$AppClassLoader@18b4aac2
    +-groovy.lang.GroovyClassLoader@78c42067
    | +-groovy.lang.GroovyClassLoader$InnerLoader@74971ed9
    +-org.codehaus.groovy.reflection.SunClassLoader@4375b013
    +-org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@2da66a44
    +-org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@285c6918
    +-org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@43fda8d9
    +-org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@65ddee5a
    +-org.codehaus.groovy.runtime.callsite.CallSiteClassLoader@59b65dce
Affect(row-cnt:14) cost in 7 ms.
[arthas@31512]$ ognl -c 18b4aac2 '@System@getProperty("java.home")'
@String[/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre]
[arthas@31512]$

todo:需总结工作中实际用到的场景

猜你喜欢

转载自blog.csdn.net/qq_26437925/article/details/114218660
今日推荐