1.什么是BTrace

BTrace是sun公司推出的一款Java 动态、安全追踪(监控)工具,可以在不用重启的情况下监控系统运行情况,方便的获取程序运行时的数据信息,如方法参数、返回值、全局变量和堆栈信息等,并且做到最少的侵入,占用最少的系统资源。

2.BTrace使用场景

在生产环境中经常遇到格式各样的问题,如OOM或者莫名其妙的进程死掉。一般情况下是通过修改程序,添加打印日志;然后重新发布程序来完成。

然而,这不仅麻烦,而且带来很多不可控的因素。有没有一种方式,在不修改原有运行程序的情况下获取运行时的数据信息呢?如方法参数、返回值、全局变量、堆栈信息等。

BTrace可以做什么?

BTrace 是一个事后工具,所谓事后工具就是在服务已经上线了,但是发现存在以下问题的时候,可以用 BTrace。

  • 比如哪些方法执行太慢,例如监控执行时间超过1s的方法

  • 查看哪些方法调用了 System.gc() ,调用栈是怎样的

  • 查看方法参数或对象属性

  • 哪些方法发生了异常

3.使用限制

为了保证trace语句只读,最小化对被检测程序造成影响, BTrace对trace脚本有一些限制(比如不能改变被trace代码中的状态):

  • 不能创建对象

  • 不能使用数组

  • 不能抛出或捕获异常

  • 不能使用循环

  • 不能使用synchronized关键字

  • 属性和方法必须使用static修饰

需要特别注意的是:不恰当的使用BTrace可能导致JVM崩溃,如在BTrace脚本使用错误的class文件,所以在上生产环境之前,务必在本地充分的验证脚本的正确性。

4.使用方法及样例

4.1使用方法

1.安装和配置

2.btrace $PID $监控脚本

3.BTrace脚本在进程重启后会失效。

注意:需要使用【btracec 监控脚本】命令对监控脚本进行预编译,可以在运行前发现错误。特别是应用到线上环境,必须强制先预编译一下,看是否报错。

4.2使用样例

1.监控方法的耗时

import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace
public class CheckOnlineStatus{
//监控某一个方法的执行时间
//这里是监控 BtraceServiceImpl 方法中 getCount 的调用情况。duration是以纳秒为单位的,所以换算成ms比较好看一点 ,其他例子也是如此考虑。
@OnMethod(clazz = "com.joson.btrace.service.impl.BtraceServiceImpl",method = "getCount",location=@Location(Kind.RETURN))
public static void printMethodRunTime(@ProbeClassName String probeClassName,@Duration long duration){
println(probeClassName + ",duration:" + duration / 1000000 + " ms");
} //统计调用时间超过100ms的方法
@OnMethod(clazz = "/com\\.kite\\.controller\\..*/",method = "/.*/",location = @Location(Kind.RETURN))
public static void slowQuery(@ProbeClassName String pcn,@ProbeMethodName String probeMethod, @Duration long duration){
if(duration > 1000000 * 100){
println(strcat("类:", pcn))
println(strcat("方法:", probeMethod));
println(strcat("时长:", str(duration / 1000000)));
}
}
}

2.查看哪些方法调用了 System.gc() ,调用栈是怎样的

import com.sun.btrace.AnyType;
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace
public class ServiceMonitor{
//查看谁调用了System.gc(),并打印调用栈
@OnMethod(clazz = "java.lang.System", method = "gc")
public static void onSystemGC() {
println("entered System.gc()");
jstack();
}
}

3.打印某个类中某一方法的入参和返回值

import com.sun.btrace.AnyType;
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace
public class ServiceMonitor{
//监控某一个方法的执行时间
@OnMethod(clazz = "com.joson.btrace.service.BtraceService",method = "getCount",location=@Location(Kind.RETURN))
public static void printMethodRunTime\(@Self Object self,String type,Integer limit,@Return AnyType result){
println( "type: " + type + " ,limit: " + limit );
println("result : " + result);
}
}
这里是监控 BtraceService 类中 getCount 方法的所有入参及返回值
对于入参,不需要打印的也可以不定义 但是定义一定要按顺序。比如参数列表不能放在返回值的后面。
​对于返回值类型 如果是非基本类型 则直接用 AnyType 类型即可。
 

5.拦截方法定义

@OnMethod 可以指定 clazz 、method、location。

由此组成了在什么时机(location 决定)监控某个类/某些类(clazz 决定)下的某个方法/某些方法(method 决定)。

定位方法

1. 精准定位

直接定位到一个类下的一个方法

2. 正则表达式定位

正则表达式在两个"/" 之间,例如下面的例子,监控 javax.swing 包下的所有方法,注意正式环境中,范围尽可能小一点,太大了性能会有影响。

@OnMethod(clazz="/javax\\.swing\\..*/", method="/.*/")
public static void swingMethods( @ProbeClassName String probeClass, @ProbeMethodName String probeMethod) {
print("entered " + probeClass + "." + probeMethod);
}

通过在拦截函数的定义里注入@ProbeClassName String probeClass, @ProbeMethodName String probeMethod 参数,告诉脚本实际匹配到的类和方法名。

3. 按接口或继承类定位

例如要匹配继承或实现了 com.kite.base 的接口或基类的,只要在类前加上 + 号就可以了,例如

@OnMethod(clazz="+com.kite.base", method="doSome")

4. 按注解定位

在前面加上 @ 即可,例如

@OnMethod(clazz="@javax.jws.WebService", method="@javax.jws.WebMethod") 

拦截时机

拦截时机由 location 决定,当然也可为同一个定位加入多个拦截时机,即可以在进入方法时拦截、方法返回时拦截、抛出异常时拦截

1. Kind.Entry与Kind.Return

分别表示函数的开始和返回,不写 location 的情况下,默认为 Kind.Entry,仅获取参数值,可以用 Kind.Entry ,要获取返回值或执行时间就要用 Kind.Return

2. Kind.Error, Kind.Throw和 Kind.Catch

表示异常被 throw 、异常被捕获还有异常发生但是没有被捕获的情况,在拦截函数的参数定义里注入一个Throwable的参数,代表异常

@OnMethod(clazz = "java.net.ServerSocket", method = "bind", location =@Location(Kind.ERROR))
public static void onBind(Throwable exception, @Duration long duration){ }

3. Kind.Call 和 Kind.Line  

Kind.Call 表示被监控的方法调用了哪些其他方法,例如:

@OnMethod(clazz = "com.kite",method = "login",location = @Location(value = Kind.CALL, clazz = "/.*/", method = "/.*/", where = Where.AFTER))
public static void onBind(@Self Object self, @TargetInstance Object instance, @TargetMethodOrField String method, @Duration long duration){
println(strcat("self: ", str(self)));
println(strcat("instance: ", str(instance)));
println(strcat("method: ", str(method)));
println(strcat("duration(ms): ", str(duration / 1000000)));
}

@Self 表示当前监控的函数所在类,如果是静态类则为空,@TargetInstance 表示函数中调用的方法或属性所在的类,如果是静态方法则为空,@TargetMethodOrField 表示调用的方法或属性,如果要获取执行时间,那么 where 必须设置为 Where.AFTER

Kind.Line 监测类是否执行到了设置的行数,例如:

@OnMethod(clazz = "com.kite.demo", location = @Location(value = Kind.LINE, line = 20))
public static void onBind() {
println("执行到第20行")
}

参考资料

https://www.gitbook.com/book/json-liu/btrace/details BTrace使用手册

https://github.com/btraceio/btrace BTrace github

https://www.jianshu.com/p/a396d8893a4c greys

Btrace使用入门的更多相关文章

  1. Java BTrace实战(1)--BTrace的入门和使用

    前言: 对线上的java服务, 往往采用日志进行问题处理和分析. 倘若日志缺乏相关的信息时, 那又该如何处理? 远程调试会影响服务的正常工作, 修改代码重新部署的方案其实时性和灵活性难以保证(线上服务 ...

  2. JVM调优(三)——基于Btrace的监控调试

    JVM调优(三)--基于Btrace的监控调试 简介 Btrace可以动态地向目标应用程序的字节码注入追踪代码 用到的技术: JavaComplierApi.JVMTI.Agent.Instrumen ...

  3. BTrace入门教程

    bin版:https://kenai.com/projects/btrace/downloads/directory/releases 源码:https://github.com/btraceio/b ...

  4. Btrace入门到熟练小工完全指南

    BTrace是神器,每一个需要每天解决线上问题,但完全不用BTrace的Java工程师,都是可疑的. BTrace的最大好处,是可以通过自己编写的脚本,获取应用的一切调用信息.而不需要不断地修改代码, ...

  5. btrace 笔记

    转载请注明原链接地址 http://www.cnblogs.com/dongxiao-yang/p/6134393.html btrace 是一个可以不用重启线上java业务查问题的神器,记一下自己折 ...

  6. BTrace使用小结

    简介 BTrace是一个安全的JVM动态追踪工具,最初为原Sun公司Kenai项目下面的一个子项目. 典型的使用场景是,“我要查个问题,可那个方法没有打印入口参数和返回结果日志”,“我想看某个方法的执 ...

  7. BTrace实战

    BTrace在解决现场问题的时候非常有用. 1.概述 1.1下载 https://github.com/btraceio/btrace,最新版本是1.3.9 目前1.3.x系列最低支持JDK1.7,要 ...

  8. JVM系列十(虚拟机性能监控神器 - BTrace).

    BTrace 是什么? BTrace 是一个动态安全的 Java 追踪工具,它通过向运行中的 Java 程序植入字节码文件,来对运行中的 Java 程序热更新,方便的获取程序运行时的数据信息,并且,保 ...

  9. 如何把Java代码玩出花?JVM Sandbox入门教程与原理浅谈

    在日常业务代码开发中,我们经常接触到AOP,比如熟知的Spring AOP.我们用它来做业务切面,比如登录校验,日志记录,性能监控,全局过滤器等.但Spring AOP有一个局限性,并不是所有的类都托 ...

随机推荐

  1. Struts2数据验证与使用Java代码进行数据验证

    Struts2数据验证 使用Java代码进行数据验证 重写ActionSupport的validate()方法 对Action类的中所有请求处理方法都会进行验证! 对Action类的数据属性进行检查, ...

  2. SaltStack概述及安装

    配置管理工具 查看文档 https://docs.saltstack.com/en/latest/ 其他工具 puppet puppet是一种Linux.Unix.windows平台的集中配置管理系统 ...

  3. Android 中各种权限深入体验及详解

    Android 中各种权限深入体验及详解 分类: Android2012-07-15 19:27 2822人阅读 评论(0) 收藏 举报 androidpermissionsinstallersyst ...

  4. JS之for...in和for...of

    for...in输入键: for...in循环有几个缺点. 数组的键名是数字,但是for...in循环是以字符串作为键名“0”.“1”.“2”等等. for...in循环不仅遍历数字键名,还会遍历手动 ...

  5. Android适配不同的设备

    感谢原作者的整理: http://blog.csdn.net/chenyjays/article/details/41308887 适配不同的语言 把UI中的字符串存储在外部文件,通过代码提取. 创建 ...

  6. c#中params关键字应用

    c#params应用 params 是C#开发语言中关键字, params主要的用处是在给函数传参数的时候用,就是当函数的参数不固定的时候. 在方法声明中的 params 关键字之后不允许任何其他参数 ...

  7. python操作socket

    Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它提供了服务器中心类,可以简化网络 ...

  8. sql server 复制表从一个数据库到另一个数据库

    sql server 复制表从一个数据库到另一个数据库 /*不同服务器数据库之间的数据操作*/ --创建链接服务器 exec sp_addlinkedserver 'ITSV ', ' ', 'SQL ...

  9. knockout 学习使用笔记----绑定map--双向绑定

    简单的方式,使用 knockout.mapping.js. 1.引入knockout.mapping.js. 2.声明模型 var model = { task:null, feedbacks:[], ...

  10. 07 nginx反向代理和nfs服务

    作业一:nginx服务二进制安装nginx包 作为web服务修改配置文件 让配置生效,验证配置 作业二:nfs服务二进制安装nfs作为共享存储挂载在三台web的网站根目录下实现,在任意一台web上修改 ...