在之前介绍Java Agent的这篇文章中,简单介绍了Java agent的应用,里面提到了基于Java agent实现的线上调试利器Btrace,当我们想定位线上问题却苦于没有日志时,可以使用Btrace attach到线上进程,动态的修改线上代码,从而达到既保留现场又能定位问题的效果。
Btrace的quickstart十分简单,并不需要有Java agent的基础。项目的git地址是Btrace,我们找到release将Btrace下载下来,下载解压之后直接点进去doc文件夹里的userguide,我们就可以按照例子进行模仿开发了。
Btrace开发流程
这里写一个简单的使用Btrace脚本的例子,方便大家熟悉下开发Btrace脚本的流程。
1.首先启动一个目标Java程序,这是我们Btrace脚本要attach的进程。
2.编写Btrace脚本,新建一个maven工程,导入Btrace相关依赖即可进行开发
@Btrace注解代表这是一个Btrace脚本。@OnMethod代表着我们注解的这个方法监控目标进程的监控点,即该方法要在什么时候运行,这里监控指定类的btrace方法,并且在方法返回时运行。params1代表着传入btrace方法的参数,若参数有多个,Btrace脚本的监控方法同样可以指定多个。被@Return注解的参数代表着btrace方法的返回值,注意这里的类型并不是Object而是AnyType。
3.使用jps命令找到目标进程的pid
4.使用终端进入之前我们下载的Btrace压缩包的bin目录,使用btrace命令指定要attach的进程pid,运行我们编写的Btrace脚本。
5.最后我们调用目标进程的btrace方法,即可在终端看到我们传入方法的参数与方法返回值了。
Btrace的注解
关于注解这里就偷下懒了。。。它的注解不多,用法也相对简单,上面的几个注解相信光看程序就可以了解其用法了,具体其他的注解以及使用大家查阅userguide里的示例程序就能够掌握,这里就不细说了。
Btrace的unsafe模式
Btrace脚本正常情况下是运行在safe模式下的,这意味着它对程序是只读的,不能对其进行修改,在safe模式下使用它有很多的限制,例如不能创建对象,不能抛出异常,不能有循环代码,不能调用外部类的方法等。正常情况下,如果我们只是想获取一些日志打印信息等,并不需要打破它的限制,但有时我们可能在跟踪方法中调用JDK原生类的方法(safe模式下只允许调用BTraceUtils类中的方法),这时我们可以在使用btrace命令时加上 -u 参数,代表着Btrace脚本将运行在unsafe模式下。
Btrace进阶
虽然Btrace功能强大,但也还是有一些限制,比如无法方法中获取局部变量的值等。这时可以使用Jboss的Byteman工具,它的功能更加强大,只是它的写法更类似于Shell脚本,对于Java程序员来说相对不太友好,但是不影响它成为一个强大的辅助工具(感兴趣的可以去官网下载并阅读文档了解用法,以后有时间会写一下它的使用)。
最后
在线上环境运行之前一定要在本地调试下你的Btrace脚本程序,否则如果一个不小心脚本报错会影响线上行为。
附赠几个有用的Btrace脚本:如何在生产环境使用Btrace进行调试,Btrace入门到熟练小工完全指南,由于二者在关于典型场景部分几个例子都差不多,所以就都贴出来了。