• btrace-(字节码)动态跟踪工具


    源码下载:https://gitee.com/hong99/spring.git (springboot_btrace)

    btrace是什么?

        github:https://github.com/btraceio/btrace

        btrace是一个用于Java平台的安全的动态跟踪工具。BTrace可用于动态跟踪运行中的Java程序(类似于DTrace用于OpenSolaris应用程序和操作系统)。BTrace动态地检测目标应用程序的类注入跟踪代码(“字节码跟踪”)。

    个人理解:就是用来做字节码跟踪的,用来解决具体执行了啥,所以日志概念只是一种实现的结果记录。

    注意:btrace底层是基于ASM 有兴趣同学看这里:http://asm.ow2.org

    下载地址:

    https://github.com/btraceio/btrace-maven (maven)

    https://github.com/btraceio/btrace.git (gradle)

    使用文档:https://github.com/btraceio/btrace/wiki#btrace

    https://github.com/btraceio/btrace/releases/tag/v2.2.2  (运行工具)

    btrace的一些约定

    1. ‍不允许创建对象

    2. 不允许创建数组

    3. 不允许抛异常

    4. 不允许catch异常

    5. 不允许随意调用其他对象或者类的方法,只允许调用com.sun.btrace.BTraceUtils中提供的静态方法(一些数据处理和信息输出工具)

    6. 不允许改变类的属性

    7. 不允许有成员变量和方法,只允许存在static public void方法

    8. 不允许有内部类、嵌套类

    9. 不允许有同步方法和同步块

    10. 不允许有循环

    11. 不允许随意继承其他类(当然,java.lang.Object除外)

    12. 不允许实现接口

    13. 不允许使用assert

    14. 不允许使用Class对象

    15. 如此多的限制,其实可以理解。BTrace要做的是,虽然修改了字节码,但是除了输出需要的信息外,对整个程序的正常运行并没有影响。

    btrace具体场景有哪些?

    btrace可以用来做代码日志跟进,以及方法执行过程中分析;

    btrace可以用来监控接口性能变慢,分析各个方法的耗时;

      btrace可以用来分析gc及调用栈信息;

    btrace可以用来分析异常信息;

    btrace可以用来收集系统相关信息;  

      ....

    btrace的使用

    下载btrace的运行包:

    https://github.com/btraceio/btrace/releases

    ff2dc94a9b20c973d2ac5457b11db81a.png

    配置环境

    mac:

    1. #jdk 配置
    2. export JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home"
    3. CLASS_PATH="$JAVA_HOME/lib"
    4. PATH=".$PATH:$JAVA_HOME/bin"
    5. #关键的配置 btrace环境
    6. BTRACE_HOME=/Users/csh/Desktop/tools/btrace
    7. export BTRACE_HOME
    8. #这个是关键
    9. export PATH=${PATH}:${BTRACE_HOME}/bin

    查看版本信息

    8bd45a644de2b54700d0c554d76bac39.png

    windows:

    BTRACE_HOME:你的路径

    PATH新增:%BTRACE_HOME%\bin

    45f13707b70d24bfbbff2eaa32e047b4.png

    e4716ab6398b516cb6b2d1e53153f212.png

    查看环境变量

    0521ff1be52903ca49991169b1e2055f.png

    引入客户端包

    1. <dependency>
    2.     <groupId>junit</groupId>
    3.     <artifactId>junit</artifactId>
    4.     <version>3.8.1</version>
    5.     <scope>test</scope>
    6. </dependency>
    7. <dependency>
    8.     <groupId>com.sun.tools.btrace</groupId>
    9.     <artifactId>btrace-client</artifactId>
    10.     <scope>system</scope>
    11.     <type>jar</type>
    12.     <systemPath>D:/tools/btrace/libs/btrace-client.jar</systemPath>
    13.     <version>2.2.2</version>
    14. </dependency>
    15. <dependency>
    16.     <groupId>com.sun.tools.btrace</groupId>
    17.     <artifactId>btrace-agent</artifactId>
    18.     <scope>system</scope>
    19.     <systemPath>D:/tools/btrace/libs/btrace-agent.jar</systemPath>
    20.     <version>2.2.2</version>
    21. </dependency>
    22. <dependency>
    23.     <groupId>com.sun.tools.btrace</groupId>
    24.     <artifactId>btrace-boot</artifactId>
    25.     <scope>system</scope>
    26.     <type>jar</type>
    27.     <systemPath>D:/tools/btrace/libs/btrace-boot.jar</systemPath>
    28.     <version>2.2.2</version>
    29. </dependency>

    注意:systemPath 为你下载包的路劲

    项目配置

    版本

    备注

    springboot

    2.4.0


    btrace

    2.2.2


    junit

    3.8.1


    port

    8386


    首页

    1. package com.hong.springboot.controller;
    2. import org.springframework.web.bind.annotation.RequestMapping;
    3. import org.springframework.web.bind.annotation.RequestParam;
    4. import org.springframework.web.bind.annotation.RestController;
    5. /**
    6.  * @author: csh
    7.  * @Date: 2021/1/12 10:16
    8.  * @Description:
    9.  */
    10. @RestController
    11. public class IndexController {
    12.     @RequestMapping("/")
    13.     public String index() {
    14.         return "成功!";
    15.     }
    16.     @RequestMapping("/1")
    17.     public String index1(@RequestParam String name) {
    18.         return name;
    19.     }
    20. }
    1. package com.hong.springboot.config;
    2. import org.openjdk.btrace.core.annotations.*;
    3. import org.openjdk.btrace.core.types.AnyType;
    4. import static org.openjdk.btrace.core.BTraceUtils.Reflective.printFields;
    5. import static org.openjdk.btrace.core.BTraceUtils.println;
    6. @BTrace
    7. public class GetIndexMethod {
    8.  
    9.     @OnMethod(clazz = "com.hong.springboot.controller.IndexController",method = "index1")
    10.     public static void pre(@Self Object self, AnyType params){
    11.         println("classPath:"+self);
    12.         printFields(params);
    13.         println("======end========");
    14.  
    15.     }
    16.  
    17.     @OnMethod(clazz = "com.hong.springboot.controller.IndexController",method = "index1",location = @Location(value = Kind.RETURN))
    18.     public static void getReturn(@Return Object obj, AnyType params, @Duration long time){
    19.         printFields(obj);
    20.         printFields(params);
    21.         println("time:"+time);
    22.         println("======end========");
    23.     }
    24. }

    启动项目~

    获取pid为:15040 (你的pid)

    b0cc410ef64e88202317723d7aa262a8.png

    启动监控,这里注意你的路劲

    btrace.bat  15040 ..\samples\GetIndexMethod.java

    特别注意啊:这里的 GetIndexMethod.java是我挪到项目中的,所以你也可以在你项目直接打开路径上接运行,不要乱写

    c144eacfcbe202c20134353cf7bebab2.png

    请求路径:http://localhost:8386/1?name=test2

    结果如下:

    6a9733983d1d0563ec1f341c7a080448.png

    编写监控时长

    1. package com.hong.springboot.config;
    2. import org.openjdk.btrace.core.annotations.*;
    3. import static org.openjdk.btrace.core.BTraceUtils.Strings.str;
    4. import static org.openjdk.btrace.core.BTraceUtils.println;
    5. import static org.openjdk.btrace.core.BTraceUtils.timeMillis;
    6. /**
    7.  * @author: csh
    8.  * @Date: 2022/6/25 16:29
    9.  * @Description:监控耗时
    10.  */
    11. @BTrace
    12. public class TlsBtrace {
    13.     @TLS
    14.     private static long startTime = 0;
    15.     @OnMethod(clazz = "com.hong.springboot.controller.IndexController", method="index1")
    16.     public static void startMethod(){
    17.         startTime = timeMillis();
    18.     }
    19.     @OnMethod(clazz = "com.hong.springboot.controller.IndexController", method="index1", location=@Location(Kind.RETURN))
    20.     public static void endMethod(@ProbeClassName String pcm, @ProbeMethodName String pmn) {
    21.         println(pcm + "." + pmn + " [Time taken: " + str(timeMillis() - startTime) + "ms]");
    22.     }
    23. }

    563fa7697b33ced47632d49da2492c9a.png

    到这里是不是跟arthas有点像~,只不过需要自己手动来编码而已。不是那么方便。当然官方提供了大量的demo可以参数路径:\samples 下面的。

    1824ad75aa551c042560c72cf10fb4ae.png

    当然了,还有另外一种 用法,通过代理模式来启动。(这里不列举)

    java -javaagent:btrace-agent.jar=[<agent-arg>[,<agent-arg>]*]? <launch-args>

    最后

    在使用btrace的时候要注意路径以及环境变量的配置,这可能唯一最容易搞错的地方,特别是运行.java的时候的路径,必须要在那个.java的路径里面进行执行或指向这个java文件所在的路径地址再执行,否则会找不着。btrace很简单也很实用,但是要与arthas来对比易用性可能差距就挺大的,但是arthas有一个非常大的问题就是在下载的时候会导致频繁FULL GC 所以看场景需要,如果那些特殊场景,公司监控很严格FULL GC就要看的就可以考虑用这个工具看看,不过使用的时候需要先将包引入这个也比较麻烦~~~~。

    参考文章

    官网:https://github.com/btraceio/btrace

    https://tech.meituan.com/2019/02/28/java-dynamic-trace.html

    https://www.oschina.net/p/btrace?hmsr=aladdin1e1

    https://www.jianshu.com/p/1b52561e3848

    https://www.cnblogs.com/danny-djy/p/9990566.html#:~:text=%20BTrace%E6%98%AF%E4%B8%80%E7%A7%8D%E5%AE%89%E5%85%A8%EF%BC%8C%E5%8A%A8%E6%80%81%E7%9A%84Java%E8%B7%9F%E8%B8%AA%E5%B7%A5%E5%85%B7%E3%80%82,BTrace%E9%80%9A%E8%BF%87%E5%8A%A8%E6%80%81%EF%BC%88%E5%AD%97%E8%8A%82%E7%A0%81%EF%BC%89%E6%A3%80%E6%B5%8B%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84Java%E7%A8%8B%E5%BA%8F%E7%9A%84%E7%B1%BB%E6%9D%A5%E5%B7%A5%E4%BD%9C%E3%80%82%20BTrace%E5%B0%86%E8%B7%9F%E8%B8%AA%E6%93%8D%E4%BD%9C%E6%8F%92%E5%85%A5%E5%88%B0%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84Java%E7%A8%8B%E5%BA%8F%E7%9A%84%E7%B1%BB%E4%B8%AD%EF%BC%8C%E5%B9%B6%E5%AF%B9%E8%B7%9F%E8%B8%AA%E7%9A%84%E7%A8%8B%E5%BA%8F%E7%B1%BB%E8%BF%9B%E8%A1%8C%E7%83%AD%E4%BA%A4%E6%8D%A2%E3%80%82

    83ffa0d74aa9a934337c99f2ec32eeed.png

  • 相关阅读:
    JAVA JDBC使用PreparedStatement实现CRUD操作
    大厂日常模型测试要求
    SpringBoot---分布式Dubbo+Zookeeper详解
    一文带你了解PCB设计中的常用基本概念
    51单片机循迹小车原理介绍和代码示例
    第一章《初学者问题大集合》第6节:IntelliJ IDEA的下载与安装
    电脑技巧:推荐5个非常实用的软件
    CVTE C/C++研发实习面试(凉)
    Kafka系列之高频面试题
    Java多线程之Thread和Runnable关于共享资源的对比
  • 原文地址:https://blog.csdn.net/qq_16498553/article/details/125476776