BTrace是什么

BTrace 是一个开源项目。旨在为 java 提供安全可靠的动态跟踪分析工具。 Btrace 基于动态字节码修改技术 (Hotswap) 来实现运行时 java 程序的跟踪和替换。Btrace的脚本是用纯java 编写的,基于一套官方提供的 annotation,使跟踪逻辑实现起来异常简单。

BTrace安装

下载链接:https://github.com/btraceio/btrace/releases , 目前最新版本为2.2.2

配置BTRACE_HOME环境变量

Path添加%BTRACE_HOME%\bin

cmd命令行输入btrace --version,出现以下界面表示成功

BTrace 注解

BTrace 注解指定应该将工具放置在何处,以及应该向追踪操作提供哪些数据。BTrace 注解可以分为3类:类注解、方法注解和参数注解。

类注解

@Btrace:表示这个类是一个BTrace脚本

方法注解

  1. @OnMethod:用于指定跟踪方法到目标类,目标方法和目标位置
  2. @OnTimer:用于指定跟踪操作定时执行。
  3. @OnError:当 trace的代码抛异常或者错误时,该注解的方法会被执行,如果同一个trace脚本中其他方法抛异常,该注解方法也会被执行。
  4. @OnEvent:用于将跟踪方法与BTrace客户端发送的“外部”事件关联起来。
  5. OnExit:用于指定BTrace代码调用"exit(int)"内置函数以完成跟踪"session"时运行的操作。
  6. @OnLowMemory:用于跟踪超过内存阈值事件
  7. @OnProbe:用于指定以避免在BTrace脚本中使用实现内部类
  8. @Sampled:为带注释的处理程序启用采样。与@OnMethod注释一起使用

参数注解

  1. @ProbeClassName:用于标记处理方法的参数,仅用户@OnMethod,该参数的值就是被跟踪的类名称
  2. @ProbeMethodName:用于表姐处理方法的参数,仅用户 @OnMethod,该参数值是被跟踪方法名称
  3. @Self:当前截取方法的封闭实例参数
  4. @Return:当前截取方法的的返回值,只对location=@Location(Kind.RETURN)生效
  5. @Duration:当前截取方法的执行时间
  6. @TargetInstance:当前截取方法内部调用的实例
  7. @TargetMethodOrField:当前截取方法内部被调用的方法名

BTrace启动方式

上篇文章介绍Java Agent的时候说过,它有两种加载方式:静态加载和动态加载。Java Agent又是BTrace底层技术之一,所以BTrace也有类似于Java Agent的加载方式的启动方式:动态启动方式和静态启动方式。

动态启动方式

动态启动方式用于快速附加到已经运行的应用程序、获取感兴趣的数据和分离、删除任何跟踪代码。

语法:btrace [-p <port>] [-cp <classpath>] <pid> <btrace-script> [<args>]

  • port是 BTrace 代理监听的端口,可选参数。classpath 是 BTrace 在编译期间搜索类的目录和 jar文件的集合。默认为“.”
  • pid是被追踪的 Java 程序的进程ID
  • btrace-script是btrace脚本程序。

静态启动方式

静态启动方式和Java Agent静态加载方式一样,在这种模式下,BTrace 甚至在应用程序启动代码运行之前就已启动。这使我们有机会追踪在应用程序生命周期的早期执行的代码。

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

agent-arg参数之间采用逗号进行分隔:

  • noServer - 不启动socket套接字服务器
  • bootClassPath - 要使用的引导类路径
  • systemClassPath - 要使用的系统类路径
  • debug - boolean类型(true/false),是否打开详细的调试消息
  • trusted- boolean类型(true/false),是否检查 btrace 限制违规
  • dumpClasses - boolean类型(true/false),是否将转换后的字节码转储到文件中
  • dumpDir - 指定转换后的类将转储到的文件夹
  • stdout - boolean类型(true/false),是否将 btrace 输出重定向到 stdout,而不是将其写入任意文件
  • probeDescPath - 搜索探测描述符 XML 的路径
  • startupRetransform - boolean类型(true/false),是否在附加时启用所有已加载类的重新转换
  • scriptdir - 包含要在代理启动时运行的脚本的目录的路径
  • scriptOutputFile - btrace脚本运行结果将要存储的路径
  • script - 在代理启动时运行的追踪脚本,脚本之间使用冒号进行分隔

要运行的脚本必须已经被btracec编译为字节码(一个*.class*文件)。

实战测试

这里只测试动态运行方式。

  1. 新建一个maven项目,引入BTrace的包

解压后会有个libs文件夹,BTrace的包可以引入本地的

<dependency><groupId>org.openjdk.btrace</groupId><artifactId>btrace-agent</artifactId><version>${btrace.version}</version><scope>system</scope><systemPath>D:\software\btrace-v2.2.1-bin\libs\btrace-agent.jar</systemPath>
</dependency><dependency><groupId>org.openjdk.btrace</groupId><artifactId>btrace-boot</artifactId><version>${btrace.version}</version><scope>system</scope><systemPath>D:\software\btrace-v2.2.1-bin\libs\btrace-boot.jar</systemPath>
</dependency><dependency><groupId>org.openjdk.btrace</groupId><artifactId>btrace-client</artifactId><version>${btrace.version}</version><scope>system</scope><systemPath>D:\software\btrace-v2.2.1-bin\libs\btrace-client.jar</systemPath>
</dependency>
  1. 新建一个MainTest 测试类
public class MainTest {public static void main(String[] args) throws InterruptedException {while (true){print(UUID.randomUUID().toString());TimeUnit.SECONDS.sleep(2);}}private static void print(String name){System.out.println("时间:"+LocalDateTime.now()+","+"hello "+name);}
}
  1. 新建一个打印方法耗时的BTrace脚本
import org.openjdk.btrace.core.BTraceUtils;
import org.openjdk.btrace.core.annotations.*;@BTrace
public class PrintMethodTime {@OnMethod(clazz = "com.example.jvmlearing.agent.MainTest",method = "print",location = @Location(value = Kind.CALL, clazz = "/.*/" , method = "/.*/", where = Where.AFTER))public static void method(@ProbeClassName String probeClass,@ProbeMethodName String probeMethod ,@Duration long duration) {BTraceUtils.print("class name= " + probeClass);BTraceUtils.print("method name =" + probeMethod);BTraceUtils.print("duration="+duration);}
}

参数解释:

  • @Location:拦截的时机,类似于AOP,在方法的执行前,执行后等时机进行拦截。
  • Kind@Location作用的探测点的种类
  • Where:探测点的位置
  1. 进入脚本所在文件夹,测试脚本
    先通过jps命令获取到MainTest 测试类的进程id,然后通过btrace命令绑定该进程id,之后就能看到脚本运行结果了

这里只是简单的使用一下BTrace,在BTrace解压后的samples文件夹下有很多例子,有兴趣的可以去看一下。

BTrace限制

BTrace最终借Instrument实现class的替换。出于安全考虑,Instrument在使用上存在诸多的限制。因此BTrace脚本也有很多限制,限制如下:

  • 不允许创建对象
  • 不允许创建数组
  • 不允许抛异常
  • 不允许catch异常
  • 不允许随意调用其他对象或者类的方法,只允许调用com.sun.btrace.BTraceUtils中提供的静态方法(一些数据处理和信息输出工具)
  • 不允许改变类的属性
  • 不允许有成员变量和方法,只允许存在static public void方法
  • 不允许有内部类、嵌套类
  • 不允许有同步方法和同步块
  • 不允许有循环(for, while, do…while)
  • 不允许随意继承其他类(当然,java.lang.Object 除外)
  • 不允许实现接口
  • 不允许使用 assert
  • 不允许使用 Class 对象
    如此多的限制,其实可以理解。BTrace要做的是,虽然修改了字节码,但是除了输出需要的信息外,对整个程序的正常运行并没有影响。

总结

其实作为 Java的动态追踪技术,站在比较底层的角度上来说,底层无非就是基ASM、Java Attach API、Instrument开发的创建。Arthas 都是针前面这些技术的一个封装而已。

动态追踪技术之BTrace相关推荐

  1. Java动态追踪技术--BTrace

    Java动态追踪技术 需求翻译官的日常工作不是在的改bug,发布代码,就是在加日志查找bug的路上.查BUG的过程是痛苦的,我们总是在不停的看代码,修改代码,添加日志,从而帮助我们发现问题,这种形式是 ...

  2. Java动态追踪技术探究

    引子 在遥远的希艾斯星球爪哇国塞沃城中,两名年轻的程序员正在为一件事情苦恼,程序出问题了,一时看不出问题出在哪里,于是有了以下对话: "Debug一下吧." "线上机器, ...

  3. Java动态追踪技术探究 1

    引子 在遥远的希艾斯星球爪哇国塞沃城中,两名年轻的程序员正在为一件事情苦恼,程序出问题了,一时看不出问题出在哪里,于是有了以下对话: "Debug一下吧." "线上机器, ...

  4. java JLabel改变大小后如何刷新_【基本功】Java动态追踪技术探究

    引子 在遥远的希艾斯星球爪哇国塞沃城中,两名年轻的程序员正在为一件事情苦恼,程序出问题了,一时看不出问题出在哪里,于是有了以下对话: "Debug一下吧." "线上机器, ...

  5. Java动态追踪技术

    Java动态追踪技术 背景 从JSP说起 Java对象行为 直接操作字节码 BTrace 尾声:三生万物 背景 在繁华的希艾斯星球爪哇国塞沃城中,两名年轻的程序员正在为一件事情苦恼,程序出问题了,一时 ...

  6. 动态追踪技术思想及应用

    动态追踪技术思想及应用 简介 静态追踪: log.metric.stats; 一个简单的示例:调试test 函数中是否存在参数为0 的场景: testDtrace.c: void test(int i ...

  7. 动态追踪技术:trace your kernel Functions!

    摘自https://zhuanlan.zhihu.com/p/27190018 动态追踪技术:trace your kernel Functions! RiboseYim RiboseYim Engi ...

  8. 动态追踪技术(中) - Dtrace、SystemTap、火焰图

    http://openresty.org/cn/presentations.html http://weibo.com/agentzh?is_all=1 http://openresty.org/po ...

  9. 2019国内某知名科技公司技术资料

    2019年过去了,国内某知名品台分享了一波他们2019年的内部的技术资料.十余年的技术积累,是他们团队继续成长的有力后盾.过去的一年间, 技术博客继续践行「从内部提炼不少优质内容,分享出来与业界同仁一 ...

最新文章

  1. 古老的SSM企业级应用
  2. 最新发布丨金融新基建系列报告:银行业六大中期趋势展望
  3. Python中的注释和算数运算符
  4. eclipse+webservice开发实例
  5. XML——XML Schema
  6. rocketmq 初探(三)
  7. 做网页很实用代码集合和CSS制作网页小技巧整理
  8. SharePoint 权限提升(SPSecurity)
  9. Oracle变异表解决方法--ORA-04091错误
  10. c语言程序机试题及答案,C语言程序设计试题及答案解析(二)
  11. Java解决找不到主类或者无法加载主类
  12. Ant design分析后台首页
  13. android qq 邮箱格式,QQ邮箱的正确格式有哪些?文件夹怎么发送呢
  14. 实例解剖一个牛 B 的融资 PPT
  15. Pygame 教程(2):重要的概念及对象
  16. Chronometer实现计时器 开始、暂停、停止功能
  17. 三重邪骨手机版怎么登录服务器未响应,三重邪骨困难版
  18. java基于springboot社区共享食堂订餐信息系统maven
  19. 曙光服务器如何重新设置u盘启动_曙光服务器常见问题
  20. mac关机变慢的解决办法

热门文章

  1. 手机淘宝H265编解码算法与工程优化
  2. c++isdigit函数_c++isdigit函数_C语言中isdigit()函数和isxdigit()函数的用法
  3. 开店攻略: 如何开婴幼儿用品店 销售中必备的四项基础修炼
  4. 微信客户端打开网页慢或出现“网络出错,轻触屏幕重新加载,错误码:-1005”
  5. 神书护体,开学大吉——计算机专业必读的10本畅销经典
  6. 【华为OD机试真题 java、python、c++】字符串解密(100%通过+复盘思路)
  7. 配置Python环境变量
  8. 优雅的气质是女人成为一道鲜活、亮丽的风景
  9. 去易宝支付面试经历9.20
  10. Zookeeper——序列化与反序列化原理