当前位置: 首页 > news >正文

Btrace使用入门

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

转载于:https://www.cnblogs.com/yeyang/p/10417853.html

相关文章:

  • GraphQL学习过程应该是这样的
  • SpiderData 2019年2月23日 DApp数据排行榜
  • 剑指offer——面试题25:合并两个 排序的链表
  • 近期前端发展计划
  • 【Leetcode】101. 对称二叉树
  • 每秒解析千兆字节的JSON解析器开源,秒杀一大波解析器!
  • 解析DELL R710服务器迁移操作内容
  • WinRAR存在严重的安全漏洞影响5亿用户
  • Git知识
  • cd命令
  • Mac 命令行美化
  • 写给自己看的发布react静态资源的方法
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • spring + angular 实现导出excel
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • 03Go 类型总结
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • angular2开源库收集
  • CEF与代理
  • Docker: 容器互访的三种方式
  • ECMAScript6(0):ES6简明参考手册
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • gitlab-ci配置详解(一)
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • JavaScript创建对象的四种方式
  • java小心机(3)| 浅析finalize()
  • Linux中的硬链接与软链接
  • React 快速上手 - 07 前端路由 react-router
  • socket.io+express实现聊天室的思考(三)
  • text-decoration与color属性
  • vue总结
  • yii2权限控制rbac之rule详细讲解
  • 官方解决所有 npm 全局安装权限问题
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 如何利用MongoDB打造TOP榜小程序
  • 如何设计一个比特币钱包服务
  • 用mpvue开发微信小程序
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • #微信小程序:微信小程序常见的配置传旨
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (Ruby)Ubuntu12.04安装Rails环境
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (过滤器)Filter和(监听器)listener
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (六)Hibernate的二级缓存
  • (五)Python 垃圾回收机制
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)Sublime Text3配置Lua运行环境
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • .NET CORE Aws S3 使用
  • .net 受管制代码
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .NET6实现破解Modbus poll点表配置文件