【基于Btrace的监控调试】_Whaleson的博客-程序员宅基地

技术标签: 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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Dreamlate_Spider/article/details/123841821

智能推荐

ubuntu下环境变量详解 bashrc, profile, environment_零度anngle的博客-程序员宅基地

在Ubuntu中有如下几个文件可以设置环境变量 /etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. /etc/environment:在登录时操作系统使用的第二个文件,系统在读取你自己的profile前,设置环境文件的环境变量 ~/.profile:在登录时用到的第三个文件是.p

手把手教你如何在Windows PC的VirtualBox上安装macOS 10.15 Catalina系统_Lucas__liu的博客-程序员宅基地

想要在VirtualBox运行任何系统,都需要有相应的ISO镜像文件,所以首先我们要获取ISO镜像文件。下边先介绍如何获取镜像文件:Step 1:从Mac App Store下载最新的Catalina 系统如果无法下载Catalina 系统,则直接跳到Step 2 结尾处下载 Catalina ISO文件Step 2:创建macOS Catalina ISO 文件找到你下载的macOS C...

Top31:Linux上部署MariaDB_mariadb远程登录_Carl_blog的博客-程序员宅基地

Top31:RHEL-Linux上部署MariaDBMariaDB的由来:安装初始化操作允许远程访问,设置防火墙放行登录更改root密码创建账户查看账户信息对账户授权例:适用:RHEL8MariaDB的由来:由于MySQL的母公司Sun在2009 年被Oracle收购后,MySQL数据库项目也随之纳入Oracle麾下,逐步演变为保持着开源软件的身份,但又申请了多项商业专利的软件系统。开源软件是全球黑客、极客、程序员等技术高手在开源社区的大旗下的公共智慧结晶,自己的劳动成果被其他公司商业化自然也伤了一大

SpringBoot过滤器 判断请求类型 获取参数 Ajax返回_lanming0326的博客-程序员宅基地

前言本文解决以下问题:SpringBoot中如何添加一个过滤器? 如何在过滤器中使用Bean? 如何判断请求的类型?GET还是POST? 如何获取请求中的参数? 如何重定向? 如何针对Ajax请求返回JSON串?如果你的关注点不在以上问题范围内,请路过。添加过滤器使用注解@WebFilter,并把它加到一个实现了Filter接口的类上,如下:@WebFilter(...

mybatis-config.xml配置文件_Qi亓天大勝的博客-程序员宅基地

为大家简单介绍一下mybatis配置文件一些参数&lt;?xml version="1.0" encoding="UTF-8" ?&gt;&lt;!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"&gt;&lt;co...

NXP RT1052 新建工程--寄存器_rt1052 start.s_ldinvicible的博客-程序员宅基地

创建工程后目录结构:名称 作用 Listings 存放编译器编译时候产生的 c/汇编/链接的列表清单 Objects 存放编译产生的调试信息、 hex 文件、预览信息、封装库等 test目录存放 startup_MIMXRT1052.s、 MIMXRT1052.h、 main.c 文件MIMXRT1052xxxxx_flexspi_nor:复制存储器分配文...

随便推点

Go-基本数据类型转换详解(int系列、float系列、string等)_go formatint 源码解读_lady_killer9的博客-程序员宅基地

参数T(v):变量v转为T类型基本数据类型转换 原类型 目标类型 方法 备注 整型、浮点型 整型、浮点型 T(v) 大数转小数超范围,溢出;浮点型转整型,小数丢失;高精度转低精度,精度丢失 任何类型 string fmt.Sprintf() 推荐 bool strconv.FormatBool(bool) int64 strconv.FormatInt(int64) ..

文本标签提取算法_梦无痕123的博客-程序员宅基地

目前想到方法1,现有分词系统提出关键词,比如ansj,hannlp,word等2,基于tfidf 算权重3,基于textrank算法,部分分词系统采取textrank 算法4,基于语言模型,ngram 算下热度5,基于聚类打标签,比如基于lda6,基于语义和知识库知识对于内容分析 总结当前主要任务是段文本如何打标签准备,还需要很多实验要验证效果

学习笔记(08):零基础搞定Python数据分析与挖掘-字符串的常用方法_火星第一公民的博客-程序员宅基地

新课上新,早鸟优惠价仅需99元! 每天前30人输入优惠码py30,立减30元! 60讲+源码+5门300元课程+讲师社群1V1答疑+社群闭门分享会=99元 10000+程序员联名推荐: 程序员必修的数据课,只看这个就够了! 【我们保证你能收获到这些:&nb...

MIUI12正在适配android11,小米10已停更半个月,基于安卓11的MIUI12即将到来_Lucien Su的博客-程序员宅基地

原标题:小米10已停更半个月,基于安卓11的MIUI12即将到来目前MIUI12稳定版第一批已经推送,第二批预计7月初会陆续推送,而内测版这边,上边年两款旗舰小米10/Pro和RedmiK30Pro已经停更将近半个月,官方表示正在适配安卓11,也就是说,这两款机型内测版下次收到更新就会吃上安卓11! 值得注意的是,这次适配是适配基于安卓11的MIUI12,而非原生安卓11Beta包,根据以往经验,...

【oracle11g,18】存储结构:临时表,手工条带化,表/索引迁移表空间,删除表,外部表_大跃ET的博客-程序员宅基地

【oracle11g,18】存储结构:临时表,手工条带化,表/索引迁移表空间,删除表,外部表

TensorFlow2.x——回调函数(callbacks)(TensorBoard、EarlyStopping、ModelCheckPoint)_一只工程狮的博客-程序员宅基地

回调函数(callbacks)(TensorBoard、EarlyStopping、ModelCheckPoint)本文主要介绍tf.Keras.callbacks中的三种回调函数:TensorBoard、EarlyStopping、ModelCheckPoint。TensorBoard:是Tensorflow自带的一个强大的可视化工具,也是一个web应用程序套件,它通过将tensor...

推荐文章

热门文章

相关标签