BTrace简介

GitHub地址:BTrace

下载地址:v1.3.11.3

官方使用教程:Btrace使用教程

使用场景

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

  1. 比如哪些方法执行太慢,例如监控执行时间超过1s的方法
  2. 查看哪些方法调用了 System.gc() ,调用栈是怎样的
  3. 查看方法参数或对象属性
  4. 哪些方法发生了异常

多说一点,为了更好解决问题,最好还要配合事前准备和进行中监控,事前准备就是埋点嘛,在一些可能出现问题的方法中进行日志输出,进行中监控就是利用一些实时监控工具,例如 VisualVM 、jmc 这些带界面的工具或者 jdk 提供的命令行工具等,再高级一点的就是利用 Graphite 这样的Metrics 工具配合 web 界面展示出来。

使用限制

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

  • BTrace class不能新建类, 新建数组, 抛异常, 捕获异常,
  • 不能调用实例方法以及静态方法(com.sun.btrace.BTraceUtils除外)
  • 不能将目标程序和对象赋值给BTrace的实例和静态field
  • 不能定义外部, 内部, 匿名, 本地类
  • 不能有同步块和方法
  • 不能有循环
  • 不能实现接口, 不能扩展类
  • 不能使用assert语句, 不能使用class字面值

Windows安装

下载对应的zip文件,解压

配置环境变量:

BTRACE_HOME=D:\Program Files\btrace-bin

Path内添加:

%BTRACE_HOME%\bin

查看版本:

$ btrace --version
BTrace v.1.3.11.3 (20181217)

Linux安装

第一步,在github 上下载 releases 版 btrace-bin-1.3.9.tgz,zip 版的没有 build 目录。

第二步,解压 btrace-bin-1.3.9.tgz 到一个目录即可,例如 /home/hongda/soft/btrace , 到这一步其实就可以用了,只是执行脚本的时候需要在 btrace 命令前加上绝对路径,如果想在任意目录可执行,进行下一步第三步。

第三步,配置环境变量,配置的环境变量包括 JAVA_HOME和 BTRACE_HOME 。

例如我的配置如下:

export JAVA_HOME=/home/hongda/soft/jdk1.8.0_111
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
export BTRACE_HOME=/home/hongda/soft/btrace
export PATH=$PATH:$BTRACE_HOME/bin

之后执行命令 source /etc/profile ,使环境变量立即生效。接下来在任意目录执行 btrace命令,都可以执行成功了。

BTrace项目配置

项目中pom.xml引用新增:

 <dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-agent</artifactId>
<version>1.3.11.3</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${basedir}/libs/btrace/btrace-agent.jar</systemPath>
</dependency>
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-boot</artifactId>
<version>1.3.11.3</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${basedir}/libs/btrace/btrace-boot.jar</systemPath>
</dependency>
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-client</artifactId>
<version>1.3.11.3</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${basedir}/libs/btrace/btrace-client.jar</systemPath>
</dependency>

或者直接安装到本地:

mvn install:install-file -Dfile=D:\Git\Hello-World\libs\btrace\btrace-boot.jar -DgroupId=com.sun.btrace -DartifactId=btrace-boot -Dversion=1.3.11.3 -Dpackaging=jar

mvn install:install-file -Dfile=D:\Git\Hello-World\libs\btrace\btrace-agent.jar -DgroupId=com.sun.btrace -DartifactId=btrace-agent -Dversion=1.3.11.3 -Dpackaging=jar

mvn install:install-file -Dfile=D:\Git\Hello-World\libs\btrace\btrace-client.jar -DgroupId=com.sun.btrace -DartifactId=btrace-client -Dversion=1.3.11.3 -Dpackaging=jar

文件夹符合无所谓,都可以

mvn install:install-file -Dfile=D:/Git/Hello-World/libs/btrace/btrace-boot.jar -DgroupId=com.sun.btrace -DartifactId=btrace-boot -Dversion=1.3.11.3 -Dpackaging=jar

上面这句也可以,然后修改pom.xml配置即可

不能够使用Program Files,发现命令里面有空格就报错

btrace预编译:

预编译:执行之前可以用预编译命令检查脚本的正确性,预编译命令为 btracec,它是一个 javac-like 命令

D:\Git\Hello-World\src\main\java\com\qhong\btrace (master -> origin)
$ btracec AllCalls1.java

btrace执行命令:

btrace 10860 NumberUtilBTrace.java

10860是要排查问题的项目运行的pid

如果要保存到本地文件中,可以使用转向命令

btrace 10860 NumberUtilBTrace.java > mylog.log

按ctrl + c ,会给出退出提示,再按 1 退出

如何定位

定位方法

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

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

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

定位接口或继承类

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

定位注解

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

如何拦截

方法进入返回拦截(Kind.Entry与Kind.Return)

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

方法异常拦截(Kind.Error, Kind.Throw和 Kind.Catch)

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

方法调用其他方法拦截(Kind.Call)

@Self 表示当前监控的函数所在类,如果是静态类则为空

@TargetInstance 表示函数中调用的方法或属性所在的类,如果是静态方法则为空

@TargetMethodOrField 表示调用的方法或属性,如果要获取执行时间,那么 where 必须设置为 Where.AFTER

方法是否执行某行数(Kind.Line)

具体操作

方法请求返回参数:

import static com.sun.btrace.BTraceUtils.println;

import com.sun.btrace.AnyType;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.ProbeClassName;
import com.sun.btrace.annotations.ProbeMethodName;
import com.sun.btrace.annotations.Return; /**
* Created by qhong on 2019/3/6 16:50
**/
@BTrace
public class AllMethodTrace { @OnMethod(
clazz="/com\\.shitou\\.huishi\\.service\\..*/",
method="queryRiskApproveList",
location=@Location(Kind.RETURN)
)
public static void anyRead(@ProbeClassName String pcn,
@ProbeMethodName String pmn,
@Return AnyType result)
{
println("ClassName: " + pcn);
println("MethodName: " + pmn);
println("ResultValue: " + result);
println();
} @OnMethod(
clazz="/com\\.shitou\\.huishi\\.service\\..*/",
method="queryRiskApproveList",
location=@Location(Kind.ENTRY)
)
public static void onBind(@ProbeClassName String pcn,
@ProbeMethodName String pmn,
Object params)
{
println("ClassName: " + pcn);
println("MethodName: " + pmn);
println("EntryValue: " + params);
println();
}
}

命令:

D:\Git\Hello-World\src\main\java\com\qhong\btrace\handmovement (master -> origin)
$ btrace 26592 AllMethodTrace.java >huishi.log

huishi.log:

ClassName: com.shitou.huishi.service.web.RiskApproveServiceImpl
MethodName: queryRiskApproveList
EntryValue: QueryRiskApproveListRequest(orgSource=JSY, productType=null, subjectName=东, subjectNo=, pageIndex=1, pageSize=30) ClassName: com.shitou.huishi.service.web.RiskApproveServiceImpl
MethodName: queryRiskApproveList
ResultValue: DataResponse(data=RiskApproveListResponse(totalCount=2, list=[QueryRiskApproveListResponse(taskType=风控审批, taskTypeStatus=0, loanOrderId=BO119643622212763658, orderType=非授信, orgName=及时雨, productName=小微企业经营贷, subjectName=中国石化, subjectNo=122334563748992, subjectNoType=null, operationName=部门经理, modifyTime=Wed Sep 19 16:16:04 CST 2018, updateTime=2018-09-19 16:16:04, taskId=291570, processInstanceId=288773, customerName=wangky, applyAmount=16000000.00, alertMessage=null, buttonStatus=[1, 2, 0], loanPlatform=null, IsFillData=false, approveStatus=a-1), QueryRiskApproveListResponse(taskType=风控审批, taskTypeStatus=0, loanOrderId=BO119643672992153605, orderType=非授信, orgName=及时雨, productName=小微企业经营贷, subjectName=东风标致, subjectNo=37889999004, subjectNoType=null, operationName=部门经理, modifyTime=Fri Dec 28 18:32:23 CST 2018, updateTime=2018-12-28 18:32:23, taskId=320560, processInstanceId=288785, customerName=wangky, applyAmount=16008000.00, alertMessage=null, buttonStatus=[1], loanPlatform=null, IsFillData=true, approveStatus=a-0)]))

参考:

【基本功】Java动态追踪技术探究

BTrace : Java 线上问题排查神器

基于Btrace的监控调试

Btrace代码生成工具

BTrace:线上问题排查工具的更多相关文章

  1. Arthas:线上问题排查工具

    安装 下载 java -jar arthas-boot.jar 查看版本: D:\Program Files\arthas $ java -jar arthas-boot.jar -version [ ...

  2. 线上问题排查神器 Arthas

    线上问题排查神器 Arthas 之前介绍过 BTrace,线上问题排查神器 BTrace 的使用,也说它是线上问题排查神器.都是神器,但今天这个也很厉害,是不是更厉害不好说,但是使用起来非常简单.如果 ...

  3. Java程序线上故障排查

    目录 一.Linux 内存和cpu 网络 磁盘 /proc文件系统 二.JVM Java堆和垃圾收集器 gc日志分析 JVMTI介绍 Attach机制 java自带工具 三.三方工具 jprofile ...

  4. Java线上问题排查思路及Linux常用问题分析命令学习

    前言 之前线上有过一两次OOM的问题,但是每次定位问题都有点手足无措的感觉,刚好利用星期天,以测试环境为模版来学习一下Linux常用的几个排查问题的命令. 也可以帮助自己在以后的工作中快速的排查线上问 ...

  5. 【转】又一次线上 OOM 排查经过

    又一次线上OOM排查经过 最近线上一个服务又出现了频繁Full GC的情况,导致提供的业务经常超时.问题出现非常不稳定,经过两周的时候,终于又捕捉到了一次Full GC,于是联系运维做Heap Dum ...

  6. JVM 线上故障排查基本操作--CPU飙高

    JVM 线上故障排查基本操作 CPU 飚高 线上 CPU 飚高问题大家应该都遇到过,那么如何定位问题呢? 思路:首先找到 CPU 飚高的那个 Java 进程,因为你的服务器会有多个 JVM 进程.然后 ...

  7. java:线上问题排查常用手段(转)

    出处:java:线上问题排查常用手段 一.jmap找出占用内存较大的实例 先给个示例代码: import java.util.ArrayList; import java.util.List; imp ...

  8. Java架构师线上问题排查,这些命令程序员一定用得到!

    Java架构师线上问题排查,这些命令程序员一定用得到! 线上问题排查,以下场景,你遇到过吗? 一.了解机器连接数情况 问题:1.2.3.4的sshd的监听端口是22,如何统计1.2.3.4的sshd服 ...

  9. JVM 线上故障排查

    JVM 线上故障排查 Linux 1.1 CPU 1.2 内存 1.3 存储 1.4 网络 一.CPU 飚高 寻找原因 二.内存问题排查 三.一般排查问题的方法 四.应用场景举例 4.1 怎么查看某个 ...

随机推荐

  1. Autofac之自动装配

    从容器中的可用服务中选择一个构造函数来创造对象,这个过程叫做自动装配.这个过程是通过反射实现的 默认 思考这么一个问题,如果注册类型中存在多个构造函数,那么Autofac会选择哪一个来创建类型的实例 ...

  2. ARE 212 - Problem Set 5

    ARE 212 - Problem Set 5Due May 1stPart I: Theory (Optional)1. Show that the parameter estimates for ...

  3. Alibaba, I'm interested in you.

    Working for Alibaba is an aspiration for some. For other it’s the possibility of lucrative stock opt ...

  4. 04.常量变量和数据类型(const)

    1.关键字 2.数据类型 告诉编译器定义一个类型变量的空间! 3.常量 4.变量 在程序运行过程中,值可以改变 变量在使用前必须先定义,定义变量前必须有相应的数据类型 标识符命名规则: (1).标识符 ...

  5. [ML] 数据处理

    可以不需要自己开发,使用CloudCompare的分割合并功能实现点云标注(labeling),生成点云训练集数据. (1)首先对点云中的物体进行分割,分割出一个一个的类别. (2)接着删除所有的SF ...

  6. [js]展开运算符

    function f(...args){ console.log(args); } f(1,2,3,4,5) [...args] = [1,2,3,4] function f(...args){ co ...

  7. python发送邮件心得体会

    利用本地smtp server发送 windows下尝试装了两个smtp server大概配置了下,发现没法生效,也没时间仔细研究了.装上foxmail发现以前可以本地发送的选项已经无法找到. 不带附 ...

  8. 获取Button脚本挂载的事件名

    (function(){ var Super = function(){}; Super.prototype = cc.Button.prototype; //实例化原型 Super.prototyp ...

  9. 201808_summary

    @Consumes @Produces分别表示入参和出参数吗 可以这样讲.但是不是很到位.是限定作用,类似于filterconsumes: 指定处理请求的提交内容类型(Content-Type),例如 ...

  10. Redishelp

    /** * @author yanming.zhang * @date 2019/1/25 21:15 */ @Component public class RedisHelp { @Autowire ...