BTrace简介
BTrace 是一个安全动态的Java追踪工具,通过动态字节码,动态替换的原理以追踪正在运行的Java程序,达到追踪的效果。
BTrace 是检查和解决线上的问题的杀器,BTrace将跟踪操作插入到正在运行的Java程序的类中,并对跟踪的程序类进行热交换。
BTrace的最大好处,是可以通过自己编写的脚本,获取应用的一切调用信息,而不需要不断地修改代码,不用重启服务,写好脚本,直接用命令执行即可,不用动原程序的代码。
Btrace能干什么
- 分析任意接口或者方法的耗时情况
- 分析不断的添加数据时,Map的扩容情况
- 分析那个方法里面调用了System.gc()方法,并打印出其调用栈
- 某些方法抛出异常时,分析其运行参数
- 统计一些接口的调用次数
- 分析一些方法的代码是否执行到了某一行
注意上面的所有操作,都是监控正在运行中的程序,基本不会产生任何影响。
BTrace实现原理
BTrace是基于动态字节码修改技术(Hotswap)向目标程序的字节码注入追踪代码。
大体的原理可以用下面的公式描述:
Client(Java compile api + attach api) + Agent(脚本解析引擎 + ASM + Instumentation) + Socket
其实 BTrace 就是使用了 java attach api 附加 agent.jar ,然后使用脚本解析引擎+asm来重写指定类的字节码,再使用 instrument 实现对原有类的替换。
BTrace工具下载
github的地址为:https://github.com/btraceio/btrace/tree/master
下载地址为:https://github.com/btraceio/btrace/releases
使用文档:https://github.com/btraceio/btrace/wiki#btrace
设置BTRACE_HOME,将bin目录加至环境变量PATH中,配置完成后执行 source .bash_profile, 在终端中输入btrace 可以看到如下内容:
$ btrace Usage: btrace <options> <pid> <btrace source or .class file> <btrace arguments> where possible options include: --version Show the version -v Run in verbose mode -o <file> The path to store the probe output (will disable showing the output in console) -u Run in trusted mode -d <path> Dump the instrumented classes to the specified path -pd <path> The search path for the probe XML descriptors -classpath <path> Specify where to find user class files and annotation processors -cp <path> Specify where to find user class files and annotation processors -I <path> Specify where to find include files -p <port> Specify port to which the btrace agent listens for clients -statsd <host[:port]> Specify the statsd server, if any
BTrace如何使用
第一步:jps命令查出需要监控的jvm pid
第二步:编写BTrace跟踪程序
第三部:执行:btrace <pid> BTrace跟踪程序
BTrace使用示例
使用起来比较简单,只需要执行btrace {javaPid} {btrace脚本}
就行,如果要把输出调试信息到控制台,要加上-v 参数,-o 参数可以把结果输出到文件中。
package com.metty.rpc.common; import java.util.Random; public class BtraceCase { public static Random random = new Random(); public int size; public static void main(String[] args) throws Exception { new BtraceCase().run(); } public void run() throws Exception { while (true) { add(random.nextInt(10), random.nextInt(10)); } } public int add(int a, int b) throws Exception { Thread.sleep(random.nextInt(10) * 100); return a + b; } }
执行add方法时,对传入参数、返回值以及执行耗时进行分析,btrace脚本:
通过jps命令获取pid为8454
执行btrace 8454 Debug.java实现对运行代码的监控,输出结果如下:
可以发现,Btrace可以获取每次执行add方法时的数据,当然Btrace能做的远远不止这些,比如获取当前jvm堆使用情况、当前线程的执行栈等等。
BTrace注意事项
Btrace脚本就是一个普通的用@Btrace注解的Java类,其中包含一个或多个public static void修饰的方法,注意拦截方法必须是用public static void 进行修饰的,如果不是静态方法则会抛出 instance methods are not allowed 这样的异常信息 如果不是public 则会提示btrace methods should be public ;如果有返回则提示信息为:btrace probe methods must return void
为了保证对目标程序不造成影响,Btrace脚本对其可以执行的动作做了很多限制,如下:
- 不能创建对象
- 不能抛出或者捕获异常
- 不能用synchronized关键字
- 不能对目标程序中的instace或者static变量
- 不能调用目标程序的instance或者static方法
- 脚本的field、method都必须是static的
- 脚本不能包括outer,inner,nested class
- 脚本中不能有循环,不能继承任何类,任何接口与assert语句
mikechen睿哥
mikechen睿哥,十余年BAT架构经验,资深技术专家,就职于阿里、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》