首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

BTrace应用简介

2012-07-15 
BTrace使用简介转:http://rdc.taobao.com/team/jm/archives/509?很多时候在online的应用出现问题时,很多时

BTrace使用简介

转:http://rdc.taobao.com/team/jm/archives/509

?

很多时候在online的应用出现问题时,很多时候我们需要知道更多的程序的运行细节,但又不可能在开发的时候就把程序中所有的运行细节都打印到日志上,通常这个时候能采取的就是修改代码,重新部署,然后再观察,但这种方法对于online应用来说不是很好,另外一方面如果碰到不好改的代码,例如引用的其他的外部的包什么的,就很麻烦了,BTrace就是一个可以在不改代码、不重启应用的情况下,动态的查看程序运行细节的工具,其官方网站在此:http://kenai.com/projects/btrace/ ,在这篇blog中,就来看看如何用BTrace来动态的监测方法的一些运行细节状况。
BTrace通过动态的挂接用java写的代码到运行时上来获取到一些运行细节,例如典型的使用btrace的方法为:
btrace -cp [btrace的jar所在的路径,默认为btrace/build下] [pid] [需要运行的java代码]
例如一段这样的代码:

import java.util.Random;public class Case1{???public static void main(String[] args) throws Exception{??????Random random=new Random();??????CaseObject object=new CaseObject();??????boolean result=true;??????while(result){?????????result=object.execute(random.nextInt(1000));?????????Thread.sleep(1000);??????}???}}public class CaseObject{???private static int sleepTotalTime=0;? ???public boolean execute(int sleepTime) throws Exception{???????System.out.println("sleep: "+sleepTime);???????sleepTotalTime+=sleepTime;???????Thread.sleep(sleepTime);???????return true;???}}

如在程序运行的情况下,想知道调用CaseObject的execute方法的以下几种情况,在BTrace中可以这么做:
1、调用此方法时传入的是什么参数,返回的是什么值,当时sleepTotalTime是多少?
BTrace脚本如下:

import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.annotations.*;@BTrace public class TraceMethodArgsAndReturn{???@OnMethod(??????clazz="CaseObject",??????method="execute",??????location=@Location(Kind.RETURN)???)???public static void traceExecute(@Self CaseObject instance,int sleepTime,@Return boolean result){?????println("call CaseObject.execute");?????println(strcat("sleepTime is:",str(sleepTime)));?????println(strcat("sleepTotalTime is:",str(get(field("CaseObject","sleepTotalTime"),instance))));?????println(strcat("return value is:",str(result)));???}}

然后直接执行btrace -cp btrace/build [pid] TraceMethodArgsAndReturn.java就可以了。
当程序中调用到caseobject的execute方法时,就会在btrace的console中输出相应的信息。
2、execute方法执行耗时是多久?
BTrace脚本如下:

????import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.annotations.*;@BTrace public class TraceMethodExecuteTime{???@TLS static long beginTime;???@OnMethod(??????clazz="CaseObject",??????method="execute"???)???public static void traceExecuteBegin(){?????beginTime=timeMillis();???}???@OnMethod(??????clazz="CaseObject",??????method="execute",??????location=@Location(Kind.RETURN)???)???public static void traceExecute(int sleepTime,@Return boolean result){??????println(strcat(strcat("CaseObject.execute time is:",str(timeMillis()-beginTime)),"ms"));???}}

3、谁调用了execute方法?
BTrace脚本如下:

import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.annotations.*;@BTrace public class TraceMethodCallee{???@OnMethod(??????clazz="CaseObject",??????method="execute"???)???public static void traceExecute(){?????println("who call CaseObject.execute :");?????jstack();???}}

4、有没有人调用CaseObject中的哪一行代码?
BTrace脚本如下:

import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.annotations.*;@BTrace public class TraceMethodLine{???@OnMethod(??????clazz="CaseObject",??????location=@Location(value=Kind.LINE,line=5)???)???public static void traceExecute(@ProbeClassName String pcn,@ProbeMethodName String pmn,int line){?????println(strcat(strcat(strcat("call ",pcn),"."),pmn));???}}

从上面可看出,在有了BTrace后,要动态的跟踪代码的运行细节还是非常爽的,更多的细节的操作请大家查看BTrace的User Guide。

?

--------------------------------------

今天同事遇到一个问题,测试环境和线上环境数据不一致,

由于我们的线上预发布环境只开发了80端口,所以无法debug,之前我们的做法就是在代码添加log,然后覆盖预发环境的相关jar,这个使用起来比较麻烦

早就听说btrace很方便,今天特意尝试了一下,

?

我们的需求就是捕捉线上某个方法的输入参数的值及返回值

step0) 安装btrace

wget http://kenai.com/projects/btrace/downloads/download/releases/release-1.2.1/btrace-bin.tar.gz并解压即可

?

step1) 产生一个btrace脚本

[java] view plaincopy
  1. import?static?com.sun.btrace.BTraceUtils.*;??import?com.sun.btrace.annotations.*;??
  2. import?java.util.Set;??import?com.sun.btrace.AnyType;??
  3. ??@BTrace?public?class?GetParam?{??
  4. ????
  5. @OnMethod(?//?【1】???????clazz="xxpackage.OfferSearchImpl",??
  6. ?????method="getOffer",???????location=@Location(Kind.RETURN)??//【2】??
  7. ?????)?????public?static?void?onGetOffer(@Return?String?result,@ProbeMethodName?String?pmn,?AnyType[]?args){?//【3】??
  8. ??????????println(pmn);??
  9. ????????println(get(field(classOf(args[0]),"recommended",false),args[0]));//【4】??????????println(result);??
  10. ????}??}??

    脚本添加注解@BTrace【1】实际就是触发点,也许是方法@OnMethod,也许是异常抛出@Error......,@OnMethod应该能覆盖绝大部分场景详见官方文档的Method Annotations【2】更细粒度的触发点,典型的就是Kind.RETURN、Kind.THROW....,有些Argument Annotations需要添加这种触发点(即仅仅第一种触发还不够),比如@Return,详见官方文档的Unannotated arguments【3】需要监控的数据,本例中使用了@Return,@ProbeMethodName,详见官方文档的Argument Annotations?【4】既然拿到了监控数据,就得想办法打印出来,本例中使用了get,field,classOf来打出某个实例的某个字段,类似java中的反射,还有很多实用方法,详见BTraceUtils的API?step2)运行

    ?

    然后启动btrace脚本${BTRACE_HOME}/bin/btrace ${JAVA_PID} ${PATH/TO}/GetParam.java

    ?

    ?

    小结

    写出了脚本之后,我们通过在不同环境中检测很快定位到了问题,如果了解了上面标出的4个关键点,并且参看官方文档以及安装文件自带的sample应该能快速的写出很多实用的监控脚本,不得不说,btrace是线上监控的利器

热点排行