今天,Team Leader推荐了一个非常棒的动态跟踪分析工具 – BTrace。由于对它的实现原理非常感兴趣,于是花了点时间研究了一下,顺便写点心得。

什么是BTrace?

BTrace是SUN Kenai云计算开发平台下的一个开源项目。旨在为java提供安全可靠的动态跟踪分析工具。

Btrace基于动态字节码修改技术(Hotswap)来实现运行时java程序的跟踪和替换。(还记得javarebel不?)

Btrace的脚本是用纯java编写的,基于一套官方提供的annotation,使跟踪逻辑实现起来异常简单。

实现原理

用一个简单的公式来表述(从左往右的使用顺序):

Sun Attach API + BTrace脚本解析引擎 + Objectweb ASM + JDK6 Instumentation

1,Sun Attach API是充当动态加载 agent 的角色。

看下面的例子:

VirtualMachine vm = VirtualMachine.attach("1688"); // 1688是进程id
String agentJarPath = "E:\\agent.jar"; // agent jar路径
vm.loadAgent(agentJarPath); // 加载agent

这个例子动态地为一个已经启动的java附加一个agent上去.

2,BTrace解析引擎解析BTrace脚本。

摘自官方的一个例子:

import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
 
@BTrace
public class HelloWorld {
@OnMethod(
clazz="java.lang.Thread",
method="start"
)
 
public static void func() {
println("about to start a thread!");
}
}

@OnMethod告诉Btrace解析引擎需要代理的类和方法。

这个例子的作用是当java.lang.Thread类的任意一个对象调用 start 方法后,会调用 func 方法。

3,解析完脚本后,Btrace会使用ASM将脚本里标注的类java.lang.Thread的字节码重写,植入跟踪代码或新的逻辑。

在上面那个例子中,Java.lang.Thread 这个类的字节码被重写了。并在start方法体尾部植入了 func 方法的调用.

ASM的使用,本文不做延伸。

4,利用instrumentation的retransformClasses,将原始字节码替换掉。

instrumentation例子:

import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
 
public class AgentMain {
public static void agentmain(String agentArgs, Instrumentation inst)
throws ClassNotFoundException, UnmodifiableClassException,
InterruptedException {
inst.addTransformer(new ClassFileTransformer() {
public byte[] transform(ClassLoader l, String className, Class<?> c, ProtectionDomain pd, byte[] b) throws IllegalClassFormatException {
// BTrace解析脚本,利用asm重写bytecode,然后classLoader加载
}
}, true);
inst.retransformClasses(java.lang.Thread.class);
}
}

关于instrumentation的一些猜测

因为 instrumentation 不能添加,修改方法,字段名,所以我怀疑它的实现原理是用 JIT 生成机器码,利用机器码的优先执行来做class替换的。JIT本身会将调用次数频繁的方法编译成机器码。

还有一种猜测就是,备份堆里的老bytecode,然后直接替换为新的。不过这种方式貌似有点暴力。

另外,替换后的字节码是在新线程内才会生效的,老线程依旧用老的字节码在执行。

替换的类原有的字段值是保持不变的。

局限性

can not create new objects.

can not create new arrays.

can not throw exceptions.

can not catch exceptions.

can not make arbitrary instance or static method calls – only the public static methods of com.sun.btrace.BTraceUtils class may be called from a BTrace program.

can not assign to static or instance fields of target program’s classes and objects. But, BTrace class can assign to it’s own static fields (“trace state” can be mutated).

can not have instance fields and methods. Only static public void returning methods are allowed for a BTrace class. And all fields have to be static.

can not have outer, inner, nested or local classes.

can not have synchronized blocks or synchronized methods.

can not have loops (for, while, do..while)

can not extend arbitrary class (super class has to be java.lang.Object)

can not implement interfaces.

can not contains assert statements.

can not use class literals.

上面是摘自官方的使用限制列表,从内容上可以看,BTrace的神通仅仅局限于只读操作。不仅强制要求java脚本需要提供public static方法.

而且,脚本里无法实例化对象,数组,不能抛异常或捕捉,不能有循环,内部类等等。

针对一些特殊对象,BTrace也是无能为力的。比如java.lang.Integer,Array等。

不过话说回来,BTrace应付大部分应用场景还是绰绰有余的。

打破局限性约束

1,自己做instrumentation的类替换,绕过BTrace的安全检查。

2,基于JVM TI自己写工具,上面的局限性将荡然无存,并且可以实现的功能会多很多。

参考资料:

BTrace 用户指南 http://kenai.com/projects/btrace/pages/UserGuide

BTrace 开发者指南 http://kenai.com/projects/btrace/pages/DeveloperGuide

Instrumentation文档http://java.sun.com/javase/6/docs/technotes/guides/instrumentation/index.html

Attach API 文档 http://java.sun.com/javase/6/docs/technotes/guides/attach/index.html

转载请注明原文链接:http://kenwublog.com/btrace-theory-analysis

java动态跟踪分析工具BTrace实现原理的更多相关文章

  1. 超好用的自带火焰图的 Java 性能分析工具 Async-profiler 了解一下

    如果你经常遇到 Java 线上性能问题束手无策,看着线上服务 CPU 飙升一筹莫展,发现内存不断泄露满脸茫然.别慌,这里有一款低开销.自带火焰图.让你大呼好用的 Java 性能分析工具 - async ...

  2. Java 性能分析工具 , 第 3 部分: Java Mission Control

    引言 本文为 Java 性能分析工具系列文章第三篇,这里将介绍如何使用 Java 任务控制器 Java Mission Control 深入分析 Java 应用程序的性能,为程序开发人员在使用 Jav ...

  3. Java 性能分析工具 , 第 2 部分:Java 内置监控工具

    引言 本文为 Java 性能分析工具系列文章第二篇,第一篇:操作系统工具.在本文中将介绍如何使用 Java 内置监控工具更加深入的了解 Java 应用程序和 JVM 本身.在 JDK 中有许多内置的工 ...

  4. TDA - Thread Dump Analyzer (Java线程分析工具)

    TDA - Thread Dump Analyzer (Java线程分析工具)http://automationqa.com/forum.php?mod=viewthread&tid=2351 ...

  5. JAVA 可视化分析工具 第12节

    JAVA 可视化分析工具  第12节 经过前几章对堆内存以及垃圾收集机制的学习,相信小伙伴们已经建立了一套比较完整的理论体系!那么这章我们就根据已有的理论知识,通过可视化工具来实践一番. 我们今天要讲 ...

  6. Java开发分析工具JProfiler的详细使用方法解析

    JProfiler 11 是一款功能强大的Java代码分析工具,JProfiler的直观UI可帮助您解决性能瓶颈,确定内存泄漏并了解线程问题且JProfiler 11 Mac破解版配置会话非常简单,第 ...

  7. Java 性能分析工具 , 第 1 部分: 操作系统工具

    引言 性能分析的前提是将应用程序内部的运行状况以及应用运行环境的状况以一种可视化的方式更加直接的展现出来,如何来达到这种可视化的展示呢?我们需要配合使用操作系统中集成的程序监控工具和 Java 中内置 ...

  8. Java 性能分析工具

    如何利用 JConsole观察分析Java程序的运行,进行排错调优 http://jiajun.iteye.com/blog/810150 如何使用JVisualVM进行性能分析 http://jia ...

  9. Java内存分析工具MAT

    MAT是一个强大的内存分析工具,可以快捷.有效地帮助我们找到内存泄露,减少内存消耗分析工具.内存中堆的使用情况是应用性能监测的重点,而对于堆的快照,可以dump出来进一步分析,总的来说,一般我们对于堆 ...

  10. java性能分析工具

    jcmd:向JVM发送诊断的命令,jvm未必会全部响应,有些需要在jvm开启相应功能才能响应.个人平时用的不是很多. SampleA: 添加        jcmd pid VM.native_mem ...

随机推荐

  1. 使用 nuxi generate 进行预渲染和部署

    title: 使用 nuxi generate 进行预渲染和部署 date: 2024/9/4 updated: 2024/9/4 author: cmdragon excerpt: 通过 nuxi ...

  2. HttpContext.SignInAsync 失效(表面解决了问题,未深入到.net core 源码去找问题,记录一下,等有时间翻一下.net core 源码试试能不能找到根本原因)

    今天在弄 identityServer4 项目的时候,发现好好的登录竟然没用了. 各种跟踪后发现是 HttpContext.SignInAsync 这个方法不写cookies了 原本经过这个方法后,会 ...

  3. 修改SpringBoot的配置文件application.yaml后启动失败

    经常碰到修改application.yaml文件之后,SpringBoot项目启动失败的,报错信息如下 Connected to the target VM, address: '127.0.0.1: ...

  4. Node.js开发博客项目笔记-搭建环境(2)

    搭建环境 首先新建blog-1文件夹,在文件夹下初始化package.json,执行命令: npm init -y 生成的package.json文件中的main属性默认值index.js改成bin/ ...

  5. JavaScript – Object.groupBy & Map.groupBy

    前言 group by 是一个很常见的功能,但 JS 却没有 build-in 的方法,一直到 es2024 才有 Object.groupBy (前生是 Array.prototype.group) ...

  6. 全网最适合入门的面向对象编程教程:50 Python函数方法与接口-接口和抽象基类

    全网最适合入门的面向对象编程教程:50 Python 函数方法与接口-接口和抽象基类 摘要: 在 Python 中,接口和抽象基类(Abstract Base Classes, ABCs)都用于定义类 ...

  7. SpringMVC —— 请求参数(传递json数据)

    接收请求中的json数据             注解       json格式(POJO)    json数组(POJO)    @RequestBody与@RequestParam区别   

  8. 如何更改Wordpress语言为中文

    在使用WordPress的时候,一般安装默认语言是英文,可以在后台设置里面直接修改站点语言为简体中文,当后台没有语言选项框的这一栏,如下图所示,该怎么办呢? 这个时候我们可以找到文件wp-config ...

  9. 墨天轮专访TDengine陶建辉:坚持做难而正确的事,三次创业成就不悔人生

    导读: 时序数据库(Time Series Database)在最近几年被越来越多的用户接受并使用,并有广泛的应用场景.云原生时序数据库 TDengine 一直稳居墨天轮时序数据库榜首,其近期的海外发 ...

  10. 有没有开发过⼀些vue插件?举例说说 - 批量引入插件

    有过,项⽬开发的时间⻓了,沉淀了不少业务通⽤全局组件,想把他们统⼀进⾏注册,就封装了⼀个⼩ 插件 当时其实⼀开始也没有什么思路,后来扒了⼀下 elementUI的源码,仿了⼀下它的写法,流程我还⼤概记 ...