JVM :Btrace监控工具

1.美图

在这里插入图片描述

2.概述

在生产环境中经常遇到格式各样的问题,如OOM或者莫名其妙的进程死掉。一般情况下是通过修改程序,添加打印日志;然后重新发布程序来完成。然而,这不仅麻烦,而且带来很多不可控的因素。有没有一种方式,在不修改原有运行程序的情况下获取运行时的数据信息呢?如方法参数、返回值、全局变量、堆栈信息等。Btrace就是这样一个工具,它可以在不修改原有代码的情况下动态地追踪java运行程序,通过hotswap技术,动态将跟踪字节码注入到运行类中,对运行代码侵入较小,对性能上的影响可以忽略不计。

在下列情况时可以使用BTrace进行分析:

  1. 接口性能变慢,分析每个方法的耗时情况;

  2. 当在Map中插入大量数据,分析其扩容情况;

  3. 分析哪个方法调用了System.gc(),调用栈如何;

  4. 执行某个方法抛出异常时,分析运行时参数;

3. 使用场景

  1. 服务慢,能找出慢在哪一步,哪个函数里么?
  2. 谁构造了一个超大的ArrayList?
  3. 什么样的入参或对象属性,导致抛出了这个异常?或进入了这个处理分支?

4.限制

为了避免Btrace脚本的消耗过大影响真正业务,所以定义了一系列不允许的事情:比如不允许调用任何类的任何方法,只能调用BTraceUtils 里的一系列方法和脚本里定义的static方法。 比如不允许创建对象,比如不允许For 循环等等,更多规定看User Guide

5.基本命令

./btrace $pid HelloWorld.java

./btrace -o mylog.log $pid HelloWorld.java
很坑新人的参数,首先,这个mylog会生成在应用的启动目录,而不是btrace的启动目录。其次,执行过一次-o之后,再执行btrace不加-o 也不会再输出回console,直到应用重启为止。

./btrace $pid HelloWorld.java > mylog.log

预编译脚本
./btracec HelloWorld.java

6.BTrace使用

下面是测试类,我是在IDEA中测试运行的

package com.java.book.jvm.chapter4;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author zzm
 */
public class BTraceTest {

    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) throws IOException {
        BTraceTest test = new BTraceTest();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        for (int i = 0; i < 10; i++) {
            reader.readLine();
            int a = (int) Math.round(Math.random() * 1000);
            int b = (int) Math.round(Math.random() * 1000);
            System.out.println(test.add(a, b));
        }
    }
}

切记先运行以上程序,然后打开jvisualvm.exe,会看见运行那个程序的进程,右击那个进程点击“Trace Application... ”就会出现以下面板

在这里插入图片描述
界面如下

在这里插入图片描述
在右边面板中放入

@OnMethod(
        clazz = "logback.BTraceTest",
        method = "add",
        location = @Location(Kind.RETURN)
    )
    public static void func(@Self logback.BTraceTest instance,int a,int b,@Return int result){
        println("调用堆栈:");
        jstack();
        println(strcat("方法参数A:",str(a)));
        println(strcat("方法参数B:",str(b)));
        println(strcat("方法结果:",str(result)));    
    }
    

如下
在这里插入图片描述
点击“start”,
在这里插入图片描述
但是我的报错

在这里插入图片描述
错误详情如下

* Starting BTrace task
** Compiling the BTrace script ...
/TracingScript.java:13: 错误: 程序包logback不存在
    public static void func(@Self logback.BTraceTest instance,int a,int b,@Return int result){
                                         ^
!!! Error occured
!!! Error occured

还没找到原因。后来发现实代码有问题

/* BTrace Script Template */
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace
public class TracingScript {
	/* put your code here */
    @OnMethod(
        clazz = "com.java.book.jvm.chapter4.BTraceTest",
        method = "add",
        location = @Location(Kind.RETURN)
    )
    public static void func(@Self com.java.book.jvm.chapter4.BTraceTest instance,int a,int b,@Return int result){
        println("调用堆栈:");
        jstack();
        println(strcat("方法参数A:",str(a)));
        println(strcat("方法参数B:",str(b)));
        println(strcat("方法结果:",str(result)));    
    }
}

改成这个样子就好了。

正常的,然后再console中回车,执行方法
在这里插入图片描述
然后就能在BTrace中看到运行结果了

在这里插入图片描述

发布了1089 篇原创文章 · 获赞 451 · 访问量 136万+

猜你喜欢

转载自blog.csdn.net/qq_21383435/article/details/104763579