开发工具系列(一):Btrace——线上Debug工具

Btrace

Btrace用于调试正在运行的系统,并且在调试时不会暂停系统。特别适用于跟踪线上问题。你可以实时监控一个系统中任何一个方法的调用,你可以知道这些方法的参数、返回值是什么,还可以知道方法调用消耗了多少时间。

Btrace不需要安装,只要下载一个包,解压即可。

Btrace用法为bin/btrace <pid> <trace-script>。其中pid是正在运行的java进程,trace-script是跟踪脚本,它其实就是一段java代码。

Hello World

首先我们模拟一个正在运行的程序,它仅有一个循环。

package com.caipeichao;

 

public class NullApp {

 

    public static void main(String[] argv) {

        new NullApp().run();

    }

 

    public void run() {

        for (int i = 0; i < 100000; i++) {

            sleep(1000);

            new MyObj().life(i);

        }

    }

 

    private static class MyObj {

 

        public void life(int n) {

            System.out.println(n);

        }

    }

 

    private void sleep(int n) {

        try {

            Thread.sleep(n);

        } catch (InterruptedException e) {

        }

    }

}

然后开启这个程序: java com.caipeichao.NullApp

通过jps命令得到这个程序的PID,这里为13348。

> jps

3034 RemoteMavenServer

2902 Main

15147 Jps

13348 NullApp

准备工作做完了,现在编写最重要的跟踪脚本。

import static com.sun.btrace.BTraceUtils.*;

import com.sun.btrace.annotations.*;

 

@BTrace

public class HelloBtrace {

  // 当com.caipeichao.NullApp.sleep方法返回时,执行该方法 

  @OnMethod(clazz="com.caipeichao.NullApp",

    method="sleep",

    location=@Location(Kind.RETURN))

  public static void onSleep() {

    println("Hello world");

  }

}

运行btrace,得到如下输出。

> btrace 13348 HelloBtrace.java

Hello world

Hello world

Hello world

Hello world

Hello world

Hello world

常用注解

名称 作用域 作用
@BTrace 声明跟踪脚本
@OnMethod(clazz,method,location) 方法 当指定方法被调用时
@OnMethod(method="<init>") 方法 当构造函数被调用时
@OnMethod(clazz="/java\\.io\\..*Input/")) 方法 方法名称正则匹配
@Location(kind) @OnMethod 指定监控方法调用前还是调用后
@Location(value=Kind.NEWARRAY, clazz="char") @OnMethod 监控新增数组
@Self 参数 表示被监控的对象
@ProbeMethodName 参数 被监控的方法名称
@ProbeClassName 参数 被监控的类名
@OnTimer(interval) 方法 定时调用某个方法
@OnLowMemory(pool,threshold) 方法 当内存不足时
@OnExit 方法 当程序退出时
@OnProbe(namespace="java.net.socket",name="bind") 方法 监控socket中的bind方法

常用方法

方法 作用
println 在本地控制台输出一行
print 在本地控制台输出
printArray 在本地控制台输出数组
jstack 打印远程方法的调用调用栈
jstackAll 输出所有线程的调用栈
exit 退出跟踪脚本
Strings.strcat 连接字符串
Reflactive.name 获取类名
Threads.name 线程名
Threads.currentThread 当前线程
deadlocks 打出死锁线程
sizeof 获取对象的大小,比如List对象就返回List.size()
Sys.Env.property 获取系统变量

原理

BTrace利用了java.lang.instrument包实现代码注入。首先通过VirtualMachine.attach(pid)连接远程JVM,然后通过VirtualMachine.loadAgent("*.jar")加载一个btrace的jar包。这个jar包最重要的代码如下。

public static void premain(String args, Instrumentation inst) {

  main(args, inst);

}

 

public static void agentmain(String args, Instrumentation inst) {

  main(args, inst);

}

 

// 将btrace的jar包添加到ClassLoader搜索目录 

private static synchronized void main(final String args, final Instrumentation inst) {

  ...

  inst.appendToBootstrapClassLoaderSearch(new JarFile(new File(path)));

  ...

  inst.appendToSystemClassLoaderSearch(new JarFile(new File(path)));

  ...

  startServer();

}

 

// 开启服务 

private static void startServer() {

  ...

  while (true) {

    try {

      ...

      handleNewClient(client);

    } catch (RuntimeException re) {

      if (isDebug()) debugPrint(re);

    } catch (IOException ioexp) {

      if (isDebug()) debugPrint(ioexp);

    }

  }

}

 

// 修改内存中的类定义 

private static void handleNewClient(final Client client) {

  ...

  inst.addTransformer(client, true);

  ...

  inst.retransformClasses(classes);

}

 

// 用ASM动态生成字节码 

abstract class Client implements ClassFileTransformer, CommandListener {

  static {

    ClassFilter.class.getClass();

    ClassReader.class.getClass();

    ClassWriter.class.getClass();

    ...

  }

 

  private byte[] instrument(Class clazz, String cname, byte[] target) {

    byte[] instrumentedCode;

    try {

    ClassWriter writer = InstrumentUtils.newClassWriter(target);

    ClassReader reader = new ClassReader(target);

    Instrumentor i = new Instrumentor(clazz, className,  btraceCode, onMethods, writer);

    ...

  }

}

一句话总结,btrace利用instrument工具修改JVM内存中的类字节码,达到注入代码的目的。

时间: 2024-12-09 01:27:09

开发工具系列(一):Btrace——线上Debug工具的相关文章

2019刘老师教你用springboot2.x开发整合微信支付的线上教育平台带源码送springboot2.x零基础入门到高级实战教程

第一部分:springboot2.x零基础入门到高级实战教程一.零基础快速入门SpringBoot2.0 1.SpringBoot2.x课程全套介绍和高手系列知识点 简介:介绍SpringBoot2.x课程大纲章节 java基础,jdk环境,maven基础 2.SpringBoot2.x依赖环境和版本新特性说明 简介:讲解新版本依赖环境和springboot2新特性概述 3.快速创建SpringBoot2.x应用之手工创建web应用 简介:使用Maven手工创建SpringBoot2.x应用 4

Map工具系列-06-销售营改增历史数据处理工具

所有cs端工具集成了一个工具面板 -打开(IE) Map工具系列-01-Map代码生成工具说明 Map工具系列-02-数据迁移工具使用说明 Map工具系列-03-代码生成BySQl工具使用说明 Map工具系列-04-SQL合并执行工具 Map工具系列-05-添加业务参数工具 Map工具系列-06-销售营改增历史数据处理工具 Map工具系列-07-TFS变更集提取工具 Map工具系列-08-map控件查看器 Map工具系列-09-文件自动对比合并工具 more... 微信小程序之明源商城系列 1.

JVM系列(七) - JVM线上监控工具

前言 通过上一篇的 JVM 垃圾回收知识,我们了解了 JVM 具体的 垃圾回收算法 和几种 垃圾回收器.理论是指导实践的工具,有了理论指导,定位问题的时候,知识和经验是关键基础,数据可以为我们提供依据. 在线上我们经常会遇见如下几个问题: 内存泄露: 某个进程突然 CPU 飙升: 线程死锁: 响应变慢. 如果遇到了以上这种问题,在 线下环境 可以有各种 可视化的本地工具 支持查看.但是一旦到 线上环境,就没有这么多的 本地调试工具 支持,我们该如何基于 监控工具 来进行定位问题? 我们一般会基于

Recon-Erlang线上系统诊断工具

Erlang系统素以稳定可靠闻名,但是它也是c实现的,也是要管理比如内存,锁等等复杂的事情,也会出现Crash,而且crash的时候大部分原因是因为内存问题.为此erlang运行期提供了强大的自省机制,帮忙用户诊断问题.自省机制过于强大,而且大部分的信息是散落在各处的,不是太资深的用户很难总体把握,而且线上系统读取这些信息的时候,也要考虑对系统的影响. 这时候recon来帮忙了, 源码在这里. Recon的定位很清晰: Recon wants to be a set of tools usabl

Cpu飚高show-busy-java-threads一件脚本排查与Arthas线上诊断工具排查实战

spring boot 模拟飚高代码 @Servicepublic class TestWhile{    /* 操作内存对象 */    ConcurrentHashMap map = new ConcurrentHashMap();    private void whileTrue(String threadName) {        // 不设置退出条件,死循环        while (true) {            // 在死循环中不断的对map执行put操作,导致内存gc

配置开发环境测试环境线上生产环境

1.正确打包 项目有三种环境: 1.本地开发环境(local) 2.开发测试环境(dev) 3.线上生产环境(product) 不同的环境有不同的配置,比如数据库连接什么的....maven打包时默认去resources文件夹下打包这些配置文件,放在WEB-INF/classes下,然后再打成war包,就能用了...现在通过修改pom.xml文件,增加三种配置,让maven打包时选择打包不同文件夹下的配置文件到WEB-INF/classes下,这样就省事儿了.... 如图所示,resources

订单导出的预发和线上的自动化对比工具

问题与背景 订单导出需要将交易数据通过报表的形式导出并提供下载給商家,供商家发货.对账等.由于交易的场景非常多,承接多个业务(微商城.零售单店.零售连锁版.餐饮),订单类型很多,新老报表的字段覆盖交易.支付.会员.优惠.发货.退款.特定业务等,合计多达120个.每次代码变更(尤其是比较大的改动),如果想要手工验证指定时间段内的绝大多数场景下绝大多数订单类型的所有字段都没有问题,在前端页面点击下载报表,然后手工对比,将是非常大的工作量.因此,迫切需要一个自动化的对比工具,对比变更分支与线上分支的导

使用tcpcopy导入线上流量进行功能和压力测试

- 假设我们要上线一个两年内不会宕机的先进架构.在上线前,免不了单元测试,功能测试,还有使用ab,webbench等等进行压力测试. 但这些步骤非生产环境下正式用户的行为.或许你会想到灰度上线,但毕竟可能会影响到部分用户,这怎么对得起我们两年内不宕机的承诺呢? 好在网易的 王斌 开发了tcpcopy, 可以导入线上流量进行功能和压力测试. tcpcopy介绍 tcpcopy是一种请求复制工具.可以将线上流量拷贝到测试机器,实时的模拟线上环境.在不影响线上用户的情况下,使用线上流量进行测试,以尽早

Map工具系列-07-TFS变更集提取工具

所有cs端工具集成了一个工具面板 -打开(IE) Map工具系列-01-Map代码生成工具说明 Map工具系列-02-数据迁移工具使用说明 Map工具系列-03-代码生成BySQl工具使用说明 Map工具系列-04-SQL合并执行工具 Map工具系列-05-添加业务参数工具 Map工具系列-06-销售营改增历史数据处理工具 Map工具系列-07-TFS变更集提取工具 Map工具系列-08-map控件查看器 Map工具系列-09-文件自动对比合并工具 more... 微信小程序之明源商城系列 1.