再谈Java 生产神器 BTrace

本文首发于我的公众号《andyqian》,期待你的关注~java

前言

  在上一篇文章《Java 生产神器  BTrace》中咱们认识了BTrace,并了解到 BTrace 脚本如何编写,如何执行,不熟悉的朋友,也能够对着文章照葫芦画瓢。但对于咱们技术人来讲,仅有这些是不够的,咱们必须弄清楚每个参数的意义,用法,才能百变不离其宗。另外,在这基础之上,还有一些更高阶的用法也是须要咱们掌握的。算法

用法

  在 BTrace 的用户指南中,将 BTrace 的经常使用用法分为类注解,方法注解,方法参数注解,它们各司其职,构形成了BTrace。下面分别介绍其使用方法:微信

类注解

  @BTrace 注解的做用域为类,咱们能够理解像Java类中的 class 关键字同样的做用。做用域与之相似的还有:DTrace,DTraceRef,这两个注解涉及到另一种脚本语言,且不经常使用,不在本文中展开。性能

方法注解

  1. @com.sun.btrace.annotations.OnMethod    字体

在方法注解中,最多见的莫过于@OnMethod,顾名思义,该注解做用于trace方法上。在该注解中,有三个很是重要的属性:this

  • clazz 表示咱们须要监听类的全限定名称,也支持匹配子类。例如:下述示例 3所述,也能够经过正则匹配多个类中的多个方法,如示例 4 中所示。spa

  • method 表示咱们须要监听的方法,一样的也支持正则匹配。.net

  • location 表示 trace 脚本在方法中执行的位置。线程

其可选值为com.sun.btrace.annotations.Kind 枚举中的值,经常使用的有如下值:3d

  • CALL   当追踪方法被调用时执行。

  • CATCH  当追踪方法捕获异常时执行。

  • ENTRY  当进入追踪方法时执行(默认值)。

  • ERROR  当追踪方法发生错误时执行。

  • LINE   当执行到指定的代码上时执行,当值为-1时,方法中的全部代码行。

  • RETURN 当追踪方法返回时执行,通常搭档 @Duration 注解进行方法耗时的记录。

  • THROW  当追踪方法抛出异常时执行。

     

2.  @com.sun.btrace.annotations.OnTimer

  该注解做用于方法上,通常用于周期性执行任务。该注解中包括两个属性,其中 经常使用的 value 属性表示时间间隔,单位为毫秒。有一个典型的案例,能够经过 OnTimer 注解来统计某个方法在必定时间段的请求次数。例如在1分钟内,某个方法的调用次数。代码以下:

待监听的方法添加以下代码:

BTraceUtils.Atomic.getAndIncrement(callCount);

OnTimer 代码以下:

static AtomicLong callCount = BTraceUtils.Atomic.newAtomicLong(1);

    @OnTimer(value=1000*60)
    public static void print() {
        BTraceUtils.println("count: "+ BTraceUtils.Atomic.get(callCount));
        BTraceUtils.println();
    }

3. @com.sun.btrace.annotations.OnError

   该注解做用于 BTrace 脚本,当BTrace类自己发生错误时会触发该方法的执行。

4. @com.sun.btrace.annotations.OnExit

当BTrace脚本中显示调用BTraceUtils.exit();方法时则会调用该注解引用的方法,调用该方法后,BTrace 脚本则会退出监听状态。示例代码以下:

@OnExit
    public static void printOnExit(int code) {
        BTraceUtils.println("====exit========"+code);
        BTraceUtils.println();
    }

5. @com.sun.btrace.annotations.OnEvent

该注解应用于事件,当咱们在使用 BTrace 客户端 Ctrl+C 时,会显示以下选项,咱们选择 2 则会发送一个默认的SIGINT事件。固然了,咱们也能够指定事件名称。例子以下:

EBUG: received com.sun.btrace.comm.OkayCommand@4148db48
Please enter your option:
    1. exit
    2. send an event
    3. send a named event
    4. flush console output
2
DEBUG: sending event command
DEBUG: received com.sun.btrace.comm.MessageCommand@282003e1
====recevied event action========

默认事件,监听代码以下:

@OnEvent
    public static void printOnEvent(){
        BTraceUtils.println("====recevied event action========");
        BTraceUtils.println();
    }

指定事件名称的事件的示例代码,(经过Ctrl+C 选择选项3 并输入相同的事件名称便可触发):

@OnEvent("evenName")
    public static void printOnEventName(){
        BTraceUtils.println("====recevied event action event Name========");
        BTraceUtils.println();
    }

方法参数注解

  1. @ProbeClassName 表示监听类的全限定名称,与 @OnMethod 注解中的 clazz 中的值是一致的。

  2. @ProbeMethodName 表示监听方法的名词,与 @OnMethod 注解中的 method 属性中的值是一致的。

  3. @Duration 表示方法的持续时间,通常用于方法耗时,在性能分析以及慢执行方面用的比较多,单位为纳秒。

  4. @Self 表示当前对象,与Java中的this关键字的做用是一致的。

  5. @Return 表示方法的返回对象。

  6. AnyType 这个很是有用,表示任意类有一个比较典型的案例:当监听方法的参数为对象时怎么办?使用AnyType轻松搞定,如示例 5 所示:

  7. @OnLowMemory 该注解用于内存监控,其有两个比较重要的参数: pool 表示须要监听的内存区域,具体名称与GC算法有关,threshold 表示阀值,超过阀值时则会触发。如示例6所示:

示例

  1. 判断是否执行过指定行:

@OnMethod(clazz="com.jq.wechat.facade.srv.impl.AuthRestServiceImpl",method = "getUserInfo",location=@Location(value=Kind.LINE,line = 48))
 public static void online(@ProbeClassName String pcn @ProbeMethodName String pmn, int line) {
     BTraceUtils.println(pcn + "." + pmn +  ":" + line);
     BTraceUtils.println();
 }

  固然,方法中的参数是可选的,也能够省略掉。其中 line 的值 就是 当前BTrace脚本监控的绝对行数。

    2. 打印系统属性以及运行:

@BTrace
public class JInfo {
 static {
     println("System Properties:");
     printProperties();
     println("VM Flags:");
     printVmArguments();
     println("OS Enviroment:");
     printEnv();
     println();
 }
}

   3. 监听全部实现 Runnalbe 接口类中的run方法:

@BTrace
public class SubtypeTracer {
 @OnMethod(
     clazz="+java.lang.Runnable",
     method="run"
 )
 public static void onRun(@ProbeClassName String pcn, @ProbeMethodName String pmn) {
     print(pcn);
     print('.');
     println(pmn);
 }
}

  4. 表示匹配 java.io中全部包括类名中包含Input关键字的类中包含read关键字的方法:

@BTrace public class MultiClass {
 @OnMethod(
     clazz="/java\\.io\\..*Input.*/",
     method="/read.*/"
 )
 public static void onread(@ProbeClassName String pcn) {
     println("read on " + pcn);
 }
}

  5. 当参数为对象类型,打印参数以及返回参数:

@OnMethod(clazz="com.jq.wechat.facade.srv.impl.AuthRestServiceImpl",method="getUserInfo",location=@Location(value=Kind.RETURN))
 public static void printUserInfo(AnyType params,@Return AnyType type){
     BTraceUtils.print("=====");
     BTraceUtils.println("====params=====");
     BTraceUtils.printFields(params);
     BTraceUtils.println("====return result=====");
     BTraceUtils.printFields(type);
     BTraceUtils.println();
 }

当参数为参数列表时,能够参考在文章《Java 生产神器  BTrace》的用法,这里就再也不详细介绍。

 6. 打印内存参数

@BTrace 
public class MemAlerter {
@OnLowMemory(
   pool = "Tenured Gen",
   threshold=6000000     
)
public static void onLowMem(MemoryUsage mu) {
   println(mu); 
}

最后

  在上述中,给出了 BTrace 脚本的使用方法,并详细介绍了经常使用参数的意义,在文章最后给出了一些例子。固然了,你也能够在BTrace的用户指南中找到更多的例子。例如:打印jstack信息,打印线程启动信息等等。


 

相关阅读:

Java 生产神器  BTrace

你的微信字体变小了吗?

Java 基本功 之 CAS

重构不彻底指南!

这里写图片描述

 扫码关注,一块儿进步

我的博客: http://www.andyqian.com

相关文章
相关标签/搜索