btrace调试利器

btrace工具地址

一.什么是BTACE

      BTrace是SUN Kenai云计算开发平台下的一个开源项目。旨在为java提供安全可靠的动态跟踪分析工具。

Btrace 是一个安全,可以动态跟踪 java 程序的一种工具。

他的操作不会对原有 java 进程产生影响,不用关闭正在运行的 java 进程,也不会修改 java 进程中的逻辑和数据。

BTrace通过动态(字节码)检测类运行Java程序。BTrace插入跟踪行动运行Java程序hotswaps跟踪程序

因此,也就成为我们线上跟踪生产代码的有力工具!

二.如何使用BTRACE

通过注解来完成跟踪类型的支持

l  方法调用

l  方法返回

l  捕捉方法异常

l  行号

l  字段get/set

l  方法调用/返回(在指定的方法中)

l  异常抛出前后

l  同步进入/退出

l  定时器

BTrace脚本

为了保证trace语句只读, BTrace对trace脚本有一些限制(比如不能改变被trace代码中的状态),跟踪类中必须要有一个静态方法,主要是通过调用BTraceUtils类来完成一些动作,并且这些动作是安全的,是BTrace规定的一个子集,详见如下描述:

l  BTrace禁止new类、数组,、抛异常、捕获异常

l  禁止调用除com.sun.btrace.BTraceUtil类的其他实例方法以及静态方法

l  BTrace1.2前不能有实例字段和方法,只能有无返回值的静态方法,所有字段也都必须是静态的。

l  禁止定义外部、内部、匿名, 本地类

l  禁止有同步块和同步方法

l  禁止有循环(for, while, do..while)

l  禁止实现接口, 不能扩展类,直接超类必须是java.lang.Object

l  禁止使用assert语句, 不能使用class字面值

l  禁止使用class字节码


方法上的注解 

l  @ OnMethod  用来指定trace的目标类和方法以及具体位置, 被注解的方法在匹配的方法执行到指定的位置会被调用。"clazz"属性用来指定目标类名, 可以指定全限定类名, 比如"java.awt.Component", 也可以是正则表达式(表达式必须写在"//"中, 比如"/java\\.awt\\..+/")。"method"属性用来指定被trace的方法. 表达式可以参考自带的例子(NewComponent.java 和 Classload.java, 关于方法的注解可以参考MultiClass.java). 有时候被trace的类和方法可能也使用了注解. 用法参考自带例子WebServiceTracker.java. 针对注解也是可以使用正则表达式, 比如像这个"@/com\\.acme\\..+/ ",也可以通过指定超类来匹配多个类, 比如"+java.lang.Runnable"可以匹配所有实现了java.lang.Runnable接口的类. 具体参考自带例子SubtypeTracer.java。

l  @OnTimer定时触发Trace,时间可以指定,单位为毫秒,具体参考自带例子 Histogram.java。

l  @OnError 当trace代码抛异常或者错误时,该注解的方法会被执行. 如果同一个trace脚本中其他方法抛异常, 该注解方法也会被执行。

l  @OnExit 当trace方法调用内置exit(int)方法(用来结束整个trace程序)时, 该注解的方法会被执行. 参考自带例子ProbeExit.java。

l  @OnEvent 用来截获"外部"btrace client触发的事件, 比如按Ctrl-C 中断btrace执行时,并且选择2,或者输入事件名称,将执行使用了该注解的方法, 该注解的value值为具体事件名称。具体参考例子HistoOnEvent.java

l  @OnLowMemory 当内存超过某个设定值将触发该注解的方法, 具体参考MemAlerter.java

l  @OnProbe 使用外部文件XML来定义trace方法以及具体的位置,具体参考示例SocketTracker1.java和java.net.socket.xml。


参数上的注解 

l  @Self 用来指定被trace方法的this,可参考例子AWTEventTracer.java 和 AllCalls1.java

l  @Return 用来指定被trace方法的返回值,可参考例子Classload.java

l  @ProbeClassName (since 1.1) 用来指定被trace的类名, 可参考例子AllMethods.java

l  @ProbeMethodName (since 1.1) 用来指定被trace的方法名, 可参考例子WebServiceTracker.java。

l  @TargetInstance (since 1.1) 用来指定被trace方法内部被调用到的实例, 可参考例子AllCalls2.java

l  @TargetMethodOrField (since 1.1) 用来指定被trace方法内部被调用的方法名, 可参考例子AllCalls1.java 和 AllCalls2.java。

 非注解的方法参数 

未使用注解的方法参数一般都是用来做方法签名匹配用的, 他们一般和被trace方法中参数出现的顺序一致. 不过他们也可以与注解方法交错使用, 如果一个参数类型声明为*AnyType[]*, 则表明它按顺序"通吃"方法所有参数. 未注解方法需要与*Location*结合使用: 

l  Kind.ENTRY-被trace方法参数

l  Kind.RETURN- 被trace方法返回值

l  Kind.THROW - 抛异常

l  Kind.ARRAY_SET, Kind.ARRAY_GET - 数组索引

l  Kind.CATCH - 捕获异常

l  Kind.FIELD_SET - 属性值

l  Kind.LINE - 行号

l  Kind.NEW - 类名

l  Kind.ERROR - 抛异常

属性上的注解 

l  @Export 该注解的静态属性主要用来与jvmstat计数器做关联. 使用该注解之后, btrace程序就可以向jvmstat客户端(可以用来统计jvm堆中的内存使用量)暴露trace程序的执行次数, 具体可参考例子ThreadCounter.java

l  @Property 使用了该注解的trace脚本将作为MBean的一个属性, 一旦使用该注解, trace脚本就会创建一个MBean并向MBean服务器注册, 这样JMX客户端比如VisualVM, jconsole就可以看到这些BTrace MBean. 如果这些被注解的属性与被trace程序的属性关联, 那么就可以通过VisualVM 和jconsole来查看这些属性了. 具体可参考例子ThreadCounterBean.java 和 HistogramBean.java。

l  @TLS 用来将一个脚本变量与一个ThreadLocal变量关联. 因为ThreadLocal变量是跟线程相关的, 一般用来检查在同一个线程调用中是否执行到了被trace的方法. 具体可参考例子OnThrow.java 和 WebServiceTracker.java

类上的注解 

l  @com.sun.btrace.annotations.DTrace 用来指定btrace脚本与内置在其脚本中的D语言脚本关联, 具体参考例子DTraceInline.java.

l  @com.sun.btrace.annotations.DTraceRef 用来指定btrace脚本与另一个D语言脚本文件关联. 具体参考例子DTraceRefDemo.java.

l  @com.sun.btrace.annotations.BTrace 用来指定该java类为一个btrace脚本文件.


附件中sample很多例子

三.实例
1.btrace放到/home/jetty下
2.切换用户到jetty ,命令sudo su jetty。因为我们jetty是用jetty用户启动的,btrace启动需要跟java程序的用户相同。
3.修改/home/jetty/.bashrc,增加
     PATH=/home/jetty/btrace/bin/:$PATH
          export PATH 
    4.source  /home/jetty/.bashrc
    5.jps 查看需要监控的pid
    6.编写btrace脚本,这里是监控订单中心fromOrder2TotalPayInfo的执行时间
package com.leo.btrace;

import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
@BTrace
public class TracingScript {
    @TLS
    private static long startTime = 0;
    @OnMethod(
            clazz = "com.dfire.soa.provider.order.service.impl.GetOrderService",
            method = "fromOrder2TotalPayInfo"
    )
    public static void startMethod() {
        startTime = timeMillis();
    }
  @OnMethod(
     clazz="com.dfire.soa.provider.order.service.impl.GetOrderService",
     method="fromOrder2TotalPayInfo",
     location=@Location(Kind.RETURN)
  )
   public static void traceExecute(){
      println(strcat("time:", str(timeMillis() - startTime)));
      println("===========================================");
   }
}

当有调用com.dfire.soa.provider.order.service.impl.GetOrderService的fromOrder2TotalPayInfo时,就会打印时间了。

      7.btrace pid TracingScript 启动btrace,可以后台启动,将日志输出到文件。
         ctrl+c输入退出提示,1回车就退出了。如果输错,需要再按下ctrl+c
四.总结
         虽然很多人用这个工具,但是我觉得还是有风险,测试环境下可以用,线上尽量别用。它是开启远程端口注入字节码。我发现当btrace启动之后,如果再开启idea远程调试程序就会挂掉。可能是远程调试不能开多个端口。
         
        

shengchou@2dfire.com
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值