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. Get all static wms goodlocation data

    sql function and store process: create function [dbo].[fun_splitin](@c varchar(),@split varchar()) r ...

  2. JMS笔记(三)

    最近重看activemq,对消息的传送确认机制有了进一步认识 1. mq在确认consumer收到消息后才会删除消息,因此consumer接收消息后应该进行ack"确认",java ...

  3. abap 变量检查

    1:sap logon中可以对变量命名进行检查 program>check>code inspector

  4. JavaScript基本概念

    JavaScript概念:JavaScript是一个弱类型语言,而且不要进行编译,是解释性语言.JavaScript最初是为了处理一些相较简单的数据验证,从而减少客户端与服务器端的通信提升效率,发展至 ...

  5. 29个人,耗时84天,硬刚Python,实验结果如下。

    真有动漫风格的编程书籍? 上图,就是日本出版的编程书籍.为什么要搞成动漫风格?因为学编程常常会枯燥,难以坚持.法国思想家布封说:所谓天才,就是坚持不懈的意思.大家学编程,转行.涨薪.加强技能,无论是何 ...

  6. jackson 流式API

    http://www.cnblogs.com/lee0oo0/articles/2652528.html Jackson提供了三种可选的JSON处理方法 1.流式API     com.fasterx ...

  7. MyEclipse破解步骤

    1.下载安装(注:安装后不要打开myeclipse,以下步骤完成方可打开) 2.解压破解文件 3.打开文件夹patch 3.全部复制 4.找到myeclipse的安装目录,打开plugins文件夹 5 ...

  8. Flask性能优化对比

    基于Flask的网关:Flask,Uwsgi,Gevent,Gunicorn(gevent),Tornado,Twisted !/usr/bin/python -- coding:utf-8 -- 美 ...

  9. (.NET高级课程笔记)泛型总结

    泛型总结 1.引入泛型:延迟声明,即在声明的时候没有指定参数类型,只有当调用的时候才会确定 其参数类型(架构师的理念:推迟一切可以推迟的) 2.如何声明和使用泛型 3.泛型的好处和原理 4.泛型类.泛 ...

  10. django框架配置mysql数据库

    django配置mysql数据库: 1.首先更改django项目文件中的settings.py的数据库配置 DATABASES = { 'default': { 'ENGINE': 'django.d ...