测试Btrace笔记
- 编写.java文件 NumberUtil.java
javac NumberUtil.java 编译class Number.class
java NumberUtil 执行class文件。
- 打开visualVm检测jvm进程
- 根据你当前的Jdk版本选择对应的visualVm,根据的visualvm版本选择正确的插件,在安装btrace有关的插件时会遇到插件依赖的情况请根据提示到官方的插件中心下载插件安装包,然后线下安装Plugin。
- 之后btrace插件会提高workbench让你舒服的编写监听脚本。
- 以下是别人对btrace的理解
>
> BTrace 是一个事后工具,所谓事后工具就是在服务已经上线了,但是发现存在以下问题的时候,可以用 BTrace。
> 1.比如哪些方法执行太慢,例如监控执行时间超过1s的方法
> 2.查看哪些方法调用了 System.gc() ,调用栈是怎样的
> 3.查看方法参数或对象属性
> 4.哪些方法发生了异常
>多说一点,为了更好解决问题,最好还要配合事前准备和进行中监控,事前准备就是埋点嘛,在一些可能出现问题的方法中进行日志输出,进行中监控就是利用一些实时监控工具,例如 VisualVM 、jmc 这些带界面的工具或者 jdk >提供的命令行工具等,再高级一点的就是利用 Graphite 这样的Metrics 工具配合 web 界面展示出来。
- 事实这样理解是正确的,因为visualVM也是把btrace插件归类未Profiler工具
- 本例的代码:
本例主要是针对所有java方法都有的返回值slot进行监听(什么是返回值的slot,这得了解JVM知识了。这里简单科普一下:在执行return指令的时候,会先把需要返回的变量(基本数据类型或者引用)放入栈顶,然后再执行return指令,return会把栈顶的数据作为函数的结果返回。如果函数中有finally语块,这个过程就不那么简单了,因为程序在执行return命令之前会先把栈顶结果保存到本地内存slot数组中,然后再进入到Finally的代码块执行finally代码,如果finally没有return指令,那么finally执行完了之后会跳转到原来return语句的前一行指令,把之前保存到slot数组的数据还原回栈顶,再然后在执行return 语句**【重要知识点!】)
```java
/* BTrace Script Template */
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
/* BTrace Script Template */
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.BTraceUtils;
@BTrace
public class TracingScript {
/* put your code here */
@OnMethod(
clazz="NumberUtil", // 声明目标类
method="sum", // 声明目标方法
location=@Location(Kind.RETURN) //声明拦截的指令位置
)
public static void func(@Return int result) { //对指令上下文监听
println("trace: =======================");
println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss")); // 打印时间
println(strcat("result:", str(result)));
jstack();
}
}
```
执行btrace script后的输出结果:
** Compiling the BTrace script ...
*** Compiled
** Instrumenting 1 classes ...
*** Done
** BTrace up&running
*** Done
** BTrace up&running
trace: =======================
result:328350
NumberUtil.sum(NumberUtil.java:15)
NumberUtil.main(NumberUtil.java:22)
trace: =======================
result:328350
NumberUtil.sum(NumberUtil.java:15)
NumberUtil.main(NumberUtil.java:22)
- 由于btrace的使用场景比较有限,对于不确定能否成功的场景可以写demo多练习,不需要贸然到生产去测试。
- 本地试玩了btrace后,把NumberUtil JVM进程部署到远程服务器,然后练习远程btrace,发现行不通。因为官方暂时没有提供基于RMI的服务接口。也就说Btrace只能检测本地JVM进程,另外Btrace修改的是线上内容的JVM字节码,这个修改是不可逆的,除非重启JVM,之后会重新加载最初的字节码(被修改前的)。