Performance Tuning -- 09 -- Btrace应用示例

原文链接:Performance Tuning – 09 – Btrace应用示例


相关文章:


这里主要展示些 Btrace 相关的应用示例


一、拦截简单参数

  • 监控方法

    @RestController
    public class HelloController {
    
        /**
         *  拦截简单参数
         */
        @GetMapping(value = "/arg/simple/{name}")
        public String argSimple(@PathVariable("name") String name) {
            return "Hello " + name + "!";
        }
    }
    
  • Btrace 脚本

    @BTrace
    public class PrintArgSimple {
    
        @OnMethod(clazz = "com.xj.controller.HelloController", method = "argSimple")
        public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
            BTraceUtils.printArray(args);
            BTraceUtils.println(pcn + " , " + pmn);
            BTraceUtils.println();
        }
    }
    
    • @ProbeClassName

      • 标记一个参数,用于保存目标类的类名
    • @ProbeMethodName

      • 标记一个参数,用于保存目标方法的方法名
    • AnyType

      • 表示任何类型的参数
  • 调用接口

    http://localhost:9998/arg/simple/World
    
  • 监控输出

    [World, ]
    com.xj.controller.HelloController , argSimple
    

二、拦截返回值

  • 监控方法

    @RestController
    public class HelloController {
    
        /**
         *  拦截返回值
         */
        @GetMapping(value = "/arg/simple/{name}")
        public String argSimple(@PathVariable("name") String name) {
            return "Hello " + name + "!";
        }
    }
    
  • Btrace 脚本

    @BTrace
    public class PrintReturn {
    
        @OnMethod(clazz = "com.xj.controller.HelloController", 
                  method = "argSimple", 
                  location = @Location(Kind.RETURN))
        public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, @Return AnyType result) {
            BTraceUtils.println(pcn + " , " + pmn + " , " + result);
            BTraceUtils.println();
        }
    }
    
    • @Return

      • 标记一个参数,用于保存返回值
  • 调用接口

    http://localhost:9998/arg/simple/World
    
  • 监控输出

    com.xj.controller.HelloController , argSimple , Hello World!
    

三、拦截构造函数

  • 监控方法

    @Data
    public class User {
    
        private int id;
        private String name;
    
        public User(int id, String name) {
            this.id = id;
            this.name = name;
        }
    }
    
    @RestController
    public class HelloController {
    
        /**
         *  拦截构造函数
         */
        @GetMapping(value = "/constructor")
        public User constructor(User user) {
            return user;
        }
    }
    
  • Btrace 脚本

    @BTrace
    public class PrintConstructor {
    
        @OnMethod(clazz = "com.xj.entity.User", method = "<init>")
        public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
            BTraceUtils.printArray(args);
            BTraceUtils.println(pcn + " , " + pmn);
            BTraceUtils.println();
        }
    }
    
    • 目标类为 User 类,目标方法为 <init> 方法 (构造方法在字节码层面显示为 <init>)
  • 调用接口

    http://localhost:9998/constructor?id=1&name=小明
    
  • 监控输出

    [1, 小明, ]
    com.xj.entity.User , <init>
    

四、拦截同名函数

  • 监控方法

    @RestController
    public class HelloController {
    
        /**
         *  拦截同名函数
         */
        @GetMapping(value = "/same1/{name}")
        public String same(@PathVariable("name") String name) {
            return "Hello " + name + "!";
        }
    
        /**
         *  拦截同名函数
         */
        @GetMapping(value = "/same2/{name}/{id}")
        public String same(@PathVariable("name") String name, @PathVariable(name = "id") int id) {
            return "Hello " + name + " " + id + "!";
        }
    }
    
  • Btrace 脚本

    @BTrace
    public class PrintSame1 {
    
        @OnMethod(clazz = "com.xj.controller.HelloController", method = "same")
        public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name) {
            BTraceUtils.println(pcn + " , " + pmn + " , " + name);
            BTraceUtils.println();
        }
    }
    
    @BTrace
    public class PrintSame2 {
    
        @OnMethod(clazz = "com.xj.controller.HelloController", method = "same")
        public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name, int id) {
            BTraceUtils.println(pcn + " , " + pmn + " , " + name + " , " + id);
            BTraceUtils.println();
        }
    }
    
    • 同名方法可以用真实参数进行区分
  • 调用接口

    http://localhost:9998/same1/World
    
    http://localhost:9998/same2/World/1
    
  • 监控输出

    com.xj.controller.HelloController , same , World
    
    com.xj.controller.HelloController , same , World , 1
    

五、拦截异常

  • 监控方法

    @RestController
    public class HelloController {
    
        /**
         *  拦截异常
         */
        @GetMapping(value = "/exception")
        public String exception() {
            try {
                System.out.println("method start");
                System.out.println(1 / 0);
                System.out.println("method end");
            } catch (Exception e) {
                // 把异常吞了
            }
            return "success";
        }
    }
    
  • Btrace 脚本

    @BTrace 
    public class PrintOnThrow {    
        // store current exception in a thread local
        // variable (@TLS annotation). Note that we can't
        // store it in a global variable!
        @TLS 
        static Throwable currentException;
    
        // introduce probe into every constructor of java.lang.Throwable
        // class and store "this" in the thread local variable.
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>"
        )
        public static void onthrow(@Self Throwable self) {//new Throwable()
            currentException = self;
        }
    
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>"
        )
        public static void onthrow1(@Self Throwable self, String s) {//new Throwable(String msg)
            currentException = self;
        }
    
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>"
        )
        public static void onthrow1(@Self Throwable self, String s, Throwable cause) {//new Throwable(String msg, Throwable cause)
            currentException = self;
        }
    
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>"
        )
        public static void onthrow2(@Self Throwable self, Throwable cause) {//new Throwable(Throwable cause)
            currentException = self;
        }
    
        // when any constructor of java.lang.Throwable returns
        // print the currentException's stack trace.
        @OnMethod(
            clazz="java.lang.Throwable",
            method="<init>",
            location=@Location(Kind.RETURN)
        )
        public static void onthrowreturn() {
            if (currentException != null) {
            	BTraceUtils.Threads.jstack(currentException);
                currentException = null;
            }
        }
    }
    
    • 当方法内部抛出的异常被吞掉时,我们可以用该 Btrace 脚本来检测被吞掉的异常
  • 调用接口

    http://localhost:9998/exception
    
  • 监控输出

    java.lang.ArithmeticException: / by zero
    	com.xj.controller.HelloController.exception(HelloController.java:57)
    	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	java.lang.reflect.Method.invoke(Method.java:498)
    	org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    	org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    	org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
    	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
    	org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
    	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
    	javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    	javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    	org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    	org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    	org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    	org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    	org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    	org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    	org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    	org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    	org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    	org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    	org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    	org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    	org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    	org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    	org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    	org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    	org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    	org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
    	org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
    	org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    	java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	java.lang.Thread.run(Thread.java:748)
    

六、拦截行号

  • 监控方法

    @RestController
    public class HelloController {
    
        /**
         *  拦截行号
         */
        @GetMapping(value = "/line")
        public String line() {
            System.out.println("line");
            return "success";
        }
    }
    
  • Btrace 脚本

    @BTrace
    public class PrintLine {
    
        @OnMethod(clazz = "com.xj.controller.HelloController", 
                  location = @Location(value = Kind.LINE, line = 70))
        public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, int line) {
            BTraceUtils.println(pcn + " , " + pmn + " , " + line);
            BTraceUtils.println();
        }
    }
    
    • Kind.LINE

      • 在某一行进行拦截
  • 调用接口

    http://localhost:9998/line
    
  • 监控输出

    com.xj.controller.HelloController , line , 70
    

七、拦截复杂参数

  • 监控方法

    @RestController
    public class HelloController {
        
        /**
         * 拦截复杂参数
         */
        @GetMapping(value = "/arg/complex")
        public User argComplex(User user) {
            return user;
        }
    }
    
  • Btrace 脚本

    @BTrace
    public class PrintArgComplex {
    
        @OnMethod(clazz = "com.xj.controller.HelloController", method = "argComplex")
        public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, User user) {
            // print all fields
            BTraceUtils.printFields(user);
            // print one field
            Field field = BTraceUtils.field("com.xj.entity.User", "name");
            BTraceUtils.println(BTraceUtils.get(field, user));
            BTraceUtils.println(pcn + " , " + pmn);
            BTraceUtils.println();
        }
    }
    
    • 由于此处我们引用了 User 类,则需要将目标程序中的 User 类加入到 classpath 中

      • 使用 Class

        btrace -cp D:\Workspace\Idea\idea-exercise-maven\jvm-tuning\target\classes 8664 PrintArgComplex.java
        
      • 使用 jar 包 (注意:此处 jar 包须为普通 jar 包,而不是可执行 jar 包)

        btrace -cp D:\Workspace\Idea\idea-exercise-maven\jvm-tuning\target\jvm-tuning-0.0.1-SNAPSHOT.jar 8664 PrintArgComplex.java
        
  • 调用接口

    http://localhost:9998/arg/complex?id=1&name=小明
    
  • 监控输出

    {id=1, name=小明, }
    小明
    com.xj.controller.HelloController , argComplex
    

八、打印参数

  • Btrace 脚本

    @BTrace
    public class PrintJInfo {
    
        static {
            BTraceUtils.println("System Properties:");
            BTraceUtils.printProperties();
            BTraceUtils.println("VM Flags");
            BTraceUtils.printVmArguments();
            BTraceUtils.println("OS Environment");
            BTraceUtils.printEnv();
            BTraceUtils.exit(0);
        }
    }
    
    • 可以在静态代码块中打印出系统参数、JVM 参数以及环境变量,类似于 jinfo
  • 监控输出

    System Properties:
    sun.desktop = windows
    awt.toolkit = sun.awt.windows.WToolkit
    file.encoding.pkg = sun.io
    java.specification.version = 1.8
    sun.cpu.isalist = amd64
    sun.jnu.encoding = GBK
    com.sun.management.jmxremote.authenticate = false
    // ...
    

九、正则表达式匹配

  • 监控方法

    @RestController
    public class HelloController {
    
        /**
         *  拦截简单参数
         */
        @GetMapping(value = "/arg/simple/{name}")
        public String argSimple(@PathVariable("name") String name) {
            return "Hello " + name + "!";
        }
    }
    
  • Btrace 脚本

    @BTrace
    public class PrintRegex {
    
        @OnMethod(clazz = "com.xj.controller.HelloController", method = "/.*/")
        public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn) {
            BTraceUtils.println(pcn + " , " + pmn);
            BTraceUtils.println();
        }
    }
    
    • 在 method 参数中,我们可以通过正则表达式来匹配相应的方法名 (此处 .* 代表匹配所有方法)
  • 调用接口

    http://localhost:9998/arg/simple/World
    
  • 监控输出

    [World, ]
    com.xj.controller.HelloController , argSimple
    
posted @ 2020-05-27 10:54  GeneXu  阅读(113)  评论(0)    收藏  举报