一、下载btrace
可以下载它的源码包,它的源码包是一个gradle项目
https://github.com/btraceio/btrace
如果只想使用它排查问题,也可以直接下载它的bin包,下载地址
https://github.com/btraceio/btrace/releases/
可以直接通过这个链接下载1.3.8版本的btrace
wget https://github.com/btraceio/btrace/releases/download/v1.3.8.3-1/btrace-bin-1.3.8.3.zip
二、配置环境变量
解压完成后需要配置环境变量BTRACE_HOME
export BTRACE_HOME=/home/work/btrace/
export PATH=$PATH:$BTRACE_HOME/bin
三、编写btrace脚本
比如我们监控spring-data-redis出现异常的时候,打印入参和异常堆栈信息:
package com;
import com.sun.btrace.AnyType;
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
import com.alibaba.fastjson.JSON;
@BTrace(unsafe=true)
public class Trace {
@OnMethod(clazz = "org.springframework.data.redis.core.DefaultHashOperations", method = "putAll", location =@Location(Kind.ERROR))
public static void putAll(Throwable exception,AnyType[] args){
println("\n##################################@#####DefaultHashOperations");
println(JSON.toJSONString(args));
println(JSON.toJSONString(exception));
println("\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
}
@OnMethod(clazz = "org.springframework.data.redis.core.DefaultSetOperations", method = "add", location =@Location(Kind.ERROR))
public static void add(Throwable exception,AnyType[] args){
println("\n##################################@#####DefaultSetOperations");
println(JSON.toJSONString(args));
println(JSON.toJSONString(exception));
println("\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
}
}
四、执行脚本:
./btrace -cp /home/work/btrace/bin/fastjson-1.2.29.jar -p 2021 5941 Trace.java
说明:
1. -cp /home/work/btrace/bin/fastjson-1.2.29.jar 指定classpath,因为引入了fastjson对参数序列化成json字符串后输出,所以这里加入了fastjson的jar包;
2. -p 2021 btrace默认端口为2020,这里更改了默认端口;
3. 5941是要追踪的jvm进程的进程id;
4. Trace.java 是第三步编写的java脚本的文件名;
异常说明
1. Port 2020 unavailable.
btrace会在remote JVM agent开启一个远程socketserver,默认端口是2020,正好如果一台台服务器有多个JVM实例需要使用btrace,当在第一个JVM上执行btrace命令后,再从其他jvm实例上执行btrace就会报错。这时候就可以使用-p参数指定端口;
2. method calls are not allowed - only calls to BTraceUtils are allowed
原因是btrace存在安全限制,不允许调用com.sun.btrace.BTraceUtils这个类中提供的方法以外的方法。但是我的脚本中使用的fastjson来讲对象转换为json字符串打印出来,所以需要解除安全限制;
3. Unable to open socket file: target process not responding or HotSpot VM not loaded
运行btrace的用户必须和启动jvm进程的用户是同一个
正确的姿势解除安全限制
网上提供了很多种方解除安全限制的方式都不靠谱,例如:
1. 使用 -u ;
2. 给btrace设置jvm参数 -Dcom.sun.btrace.unsafe=true
如果,按上面两种方式是无法解除安全限制的,正确的解除安全限制的姿势是给btrace的jvm启动脚本添加了
-Dcom.sun.btrace.unsafe=true参数后,还需要在java脚本类的@Btrace注解上加上unsafe=true:
@BTrace(unsafe=true)