【基于Btrace的监控调试】

Btrace简介(Docker可选择阿里arthas)

建议使用JDK8

        Btrace可以动态地向目标应用程序的字节码注入追踪代码。

        JavaComplierApi、JVMTI、Instrumentation+ASM

Btrace安装入门

Btrace
Btrace_V2.2.2

        新建环境变量BTRACE_HOME

        添加Path:%BTRACE_HOME%\bin

两种运行脚本方式

        在JVisualVM中添加Btrace插件,添加classpath

        使用命令行btrace <pid> <trace_script>

pom文件添加Btrace依赖

<dependency>
	<groupId>org.openjdk.btrace</groupId>
	<artifactId>btrace-agent</artifactId>
	<version>2.2.2</version>
	<type>jar</type>
	<scope>system</scope>
	<systemPath>%BTRACE_HOME%\libs\btrace-agent.jar</systemPath>
</dependency>

<dependency>
	<groupId>org.openjdk.btrace</groupId>
	<artifactId>btrace-boot</artifactId>
	<version>2.2.2</version>
	<type>jar</type>
	<scope>system</scope>
	<systemPath>%BTRACE_HOME%\libs\btrace-boot.jar</systemPath>
</dependency>

<dependency>
	<groupId>org.openjdk.btrace</groupId>
	<artifactId>btrace-client</artifactId>
	<version>2.2.2</version>
	<type>jar</type>
	<scope>system</scope>
	<systemPath>%BTRACE_HOME%\libs\btrace-client.jar</systemPath>
</dependency>

编写一个测试方法

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController()
@RequestMapping("/btrace")
public class BTraceController {

    @GetMapping("/arg1")
    public String arg1(@RequestParam("name") String name){
        return "Hello," +name;
    }
}

Btrace追踪类

@BTrace
public class PrintArgsSimple {

    @OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",
        method = "arg1",
        location = @Location(Kind.ENTRY)//在什么时候拦截,entry是指入口的地方
    )
    public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args){
        BTraceUtils.printArray(args);
        BTraceUtils.println(pcn +"\t" + pmn);
    }
}

启动服务并查看服务进程

jps -l

在这里插入图片描述

在Btrace追踪类的同级目录下执行

btrace 5680 PrintArgsSimple.java

在这里插入图片描述
在这里插入图片描述

2 Btrace使用详解

2.1 拦截方法

2.1.1 普通方法@OnMethod(clazz="",method="")

2.1.2 构造函数@OnMethod(clazz="",method="<init>")

构造函数程序

@GetMapping("/construct")
public String construct(User user){
    return user.toString();
}

public class User {
    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

拦截器

@BTrace
public class PrintConstructor {
    @OnMethod(clazz = "com.whaleson.solar.domain.User",method = "<init>")
    public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args){
        BTraceUtils.printArray(args);
        BTraceUtils.println(pcn +"\t" + pmn);
        BTraceUtils.println();
    }
}

在这里插入图片描述

2.1.3 拦截同名函数,用参数区分

同名函数程序

@GetMapping("/arg1")
public String same(@RequestParam("name") String name){
    return "Hello," +name;
}
@GetMapping("/arg2")
public String same(@RequestParam("name") String name,@RequestParam("gender") String gender){
    return "Hello," +name +"\t" +gender;
}

拦截器

@BTrace
public class PrintSame {

    @OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",
        method = "same"
    )
    public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name,String gender){
        BTraceUtils.println(pcn +"\t" + pmn);
        BTraceUtils.println(name +"\t" + gender);
        BTraceUtils.println();
   

在这里插入图片描述

2.2 拦截时机

2.2.1 Kind.ENNTRY:入口,默认值

2.2.2 Kind.RETURN:返回

编写方法类

@GetMapping("/construct")
public String construct(User user){
    return user.toString();
}

拦截类

需要注意的是如果需要拦截返回值时,需要在拦截的请求参数上加@Return

import org.openjdk.btrace.core.BTraceUtils;
import org.openjdk.btrace.core.annotations.*;
import org.openjdk.btrace.core.types.AnyType;

@BTrace
public class PrintReturn {
    @OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",
            method = "construct",
            location = @Location(Kind.RETURN)
    )
    public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, @Return AnyType arg){
        BTraceUtils.println(pcn +"\t" + pmn);
        BTraceUtils.println(arg);
        BTraceUtils.println();
    }
}

在这里插入图片描述

2.2.3 Kind.THROW:异常

异常类

@GetMapping("/exception")
public String exception(){
    try {
        System.out.println("start");
        System.out.println(1/0);
        System.out.println("end");
    }catch (Exception e){
        new Throwable("666");

    }
    return "succeed";
}

拦截类


import org.openjdk.btrace.core.BTraceUtils;
import org.openjdk.btrace.core.annotations.*;

/**
 * This example demonstrates printing stack trace
 * of an exception and thread local variables. This
 * trace script prints exception stack trace whenever
 * java.lang.Throwable's constructor returns. This way
 * you can trace all exceptions that may be caught and
 * "eaten" silently by the traced program. Note that the
 * assumption is that the exceptions are thrown soon after
 * creation [like in "throw new FooException();"] rather
 * that be stored and thrown later.
 */
@BTrace
public class PrintOnThrow {
    // store current exception in a thread local
    // variable (@TLS annotation). Note that we can't
    // store it in a global variable!
    @TLS
    static Throwable currentException;

    // introduce probe into every constructor of java.lang.Throwable
    // class and store "this" in the thread local variable.
    @OnMethod(
            clazz = "java.lang.Throwable",
            method = "<init>"
    )
    public static void onthrow(@Self Throwable self) {
        BTraceUtils.println(1);
        currentException = self;
    }

    @OnMethod(
            clazz = "java.lang.Throwable",
            method = "<init>"
    )
    public static void onthrow1(@Self Throwable self, String s) {
        BTraceUtils.println(2);
        currentException = self;
    }

    @OnMethod(
            clazz = "java.lang.Throwable",
            method = "<init>"
    )
    public static void onthrow1(@Self Throwable self, String s, Throwable cause) {
        BTraceUtils.println(3);
        currentException = self;
    }

    @OnMethod(
            clazz = "java.lang.Throwable",
            method = "<init>"
    )
    public static void onthrow2(@Self Throwable self, Throwable cause) {
        BTraceUtils.println(4);
        currentException = self;
    }

    // when any constructor of java.lang.Throwable returns
    // print the currentException's stack trace.
    @OnMethod(
            clazz = "java.lang.Throwable",
            method = "<init>",
            location = @Location(Kind.RETURN)
    )
    public static void onthrowreturn() {
        BTraceUtils.println(5);
        if (currentException != null) {
            BTraceUtils.Threads.jstack(currentException);
            BTraceUtils.println("=====================");
            currentException = null;
        }
    }
}

2.2.4 Kind.Line:行

作用,查看指定行是否执行

测类方法
在这里插入图片描述
拦截类

@BTrace
public class PrintLine {

    @OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",method = "exception",
        location = @Location(value = Kind.LINE,line = 31)
    )
    public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, int line){
        BTraceUtils.println(pcn +"\t" + pmn);
        BTraceUtils.println(line);
        BTraceUtils.println();
    }
}

2.3 拦截this、参数、返回值

2.3.1 this:@self

2.3.2 入参:可以用AnyType,也可以用真实类型,同名的用真实的

拦截类

@BTrace
public class PrintArgComplex {

    @OnMethod(clazz = "com.whaleson.solar.practice.btrace.BTraceController",
            method = "construct",location = @Location(Kind.ENTRY))
    public void print(@ProbeClassName String pcn, @ProbeMethodName String pmn, User user){
        Field fieldName = BTraceUtils.field("com.whaleson.solar.domain.User", "name");

        BTraceUtils.println(BTraceUtils.get(fieldName,user));

        BTraceUtils.println();

    }
}

执行拦截类

btrace 9684 PrintArgComplex.java

执行结果

btrace INFO: Attaching BTrace to PID: 9684
PrintArgComplex.java:3: 错误: 程序包com.whaleson.solar.domain不存在
import com.whaleson.solar.domain.User;
                                ^
PrintArgComplex.java:14: 错误: 找不到符号
    public void print(@ProbeClassName String pcn, @ProbeMethodName String pmn, User user){
                                                                               ^
  符号:User
  位置:com.whaleson.solar.utils.PrintArgComplex
BTrace compilation failed

执行时将User类增加到classpath

btrace -cp "D:\workspace\idea\Solar\target\classes" 9684 PrintArgComplex.java

在这里插入图片描述
使用正则表达式匹配方法

import org.openjdk.btrace.core.annotations.BTrace;
import org.openjdk.btrace.core.annotations.Injected;
import org.openjdk.btrace.core.annotations.OnMethod;
import org.openjdk.btrace.core.annotations.ProbeClassName;
import org.openjdk.btrace.core.annotations.ProbeMethodName;
import org.openjdk.btrace.core.annotations.Self;
import org.openjdk.btrace.core.annotations.ServiceType;
import org.openjdk.btrace.services.impl.Printer;

/**
 * This script traces method entry into every method of
 * every class in javax.swing package! Think before using
 * this script -- this will slow down your app significantly!!
 */
@BTrace
public class AllMethods {
    @Injected(ServiceType.RUNTIME)
    private static Printer printer;

    @OnMethod(
            clazz = "/javax\\.swing\\..*/",
            method = "${m}"
    )
    public static void m(@Self Object o, @ProbeClassName String probeClass, @ProbeMethodName String probeMethod) {
        printer.println("this = " + o);
        printer.print("entered " + probeClass);
        printer.println("." + probeMethod);
    }
}

输出系统参数

import org.openjdk.btrace.core.BTraceUtils;
import org.openjdk.btrace.core.annotations.BTrace;

@BTrace
public class PrintJInfo {

    static {
        BTraceUtils.println("System Properties:");
        BTraceUtils.printProperties();
        BTraceUtils.println("VM Flags");
        BTraceUtils.printVmArguments();
        BTraceUtils.println("OS Enviroment");
        BTraceUtils.printEnv();
        BTraceUtils.exit(0);
    }
}

2.3.3 返回值@Return

注意事项

        默认只能本机调试;

        生产环境下可以使用,但是被修改的字节码不会被还原

比BTrace更强大的监控工具-阿里巴巴的Arthas

Arthas

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值