`
victorzhzh
  • 浏览: 202060 次
  • 来自: ...
社区版块
存档分类
最新评论

Btrace系列之一:Btrace的基本原理

阅读更多

 

写在前面的话:Btrace系列是我将平时里学习和使用Btrace的一些经验的总结,拿出来和大家一起交流一下,希望在这个过程中能找寻出自己理解或使用上的错误之处。

 

一、Btrace的简介:

    Btrace是由Kenai 开发的一个开源项目,是一种动态跟踪分析JAVA源代码的工具。它可以用来帮我们做运行时的JAVA程序分析,监控等等操作,当然,它也不是万能的,BTrace也有一些使用上的限制,如:不能在脚本中新建类等等,这些在官方网站上有很详细的介绍,大家有兴趣可以查看:http://kenai.com/projects/btrace/pages/UserGuide。

 

二、JDK6的几个新特性:

     Btrace是由:Attach API + BTrace脚本解析引擎 + ASM + JDK6 Instumentation组成,这里要注意最后一项是JDK6的Instumentation,为什么一定要是JDK6呢?我们就要来看一下JDK6为我们提供了什么:

1、虚拟机启动后的Instumentation:

        Instumentation早在JDK5的时候就已经提出了,但是它有个局限性,premain函数只能在main函数之前被运行(对于Instumentation不熟悉的请去Sun官网查看),而JDK6之后提供了一个叫做agentmain的函数,它可以在main函数运行后在运行,代码如下:

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

 这个函数的功能通premain函数一样,可以对类进行各种操作。同premain函数一样,在manifest 文件里面设置“Agent-Class”来指定包含 agentmain 函数的类。

2、Instumentation提供的新方法retransformClasses:

        这个新方法可以在agentmain函数中调用,它的功能和redefineClasses 一样,可以修改类的定义且是批量的。        

3、BootClassPath和SystemClassPath的动态指定:

       在JDK6之前,我们知道可以通过系统参数或者虚拟机启动参数,设置一个虚拟机运行时的boot class加载路径和system class加载路径,但是在启动后,这个路径是不可以修改的,并且,我们要在启动后再去加载一个*.jar文件是不可能的,但是在JDK6以后,这个规定被打破了,可以使用Instrumentation的appendToBootstrapClassLoaderSearch和appendToSystemClassLoaderSearch来修改路径或加载新的*.jar(注意:虽然实际的classpath被修改了,但是在property中的java.class.path却没有受任何影响)。

 

正因为以上的新特性,才缔造出了Btrace的想法以至于最后的实现。

 

三、Btrace的原理:

Btrace首先是通过Attach API中提供的VirtualMachine.attach(PID)方法来获得要监控的JVM,然后使用VirtualMachine.loadAgent("*.jar")方法来加载jar文件,这个jar文件中会包含Btrace的一个很重要的类com.sun.btrace.agent.Main,这个类里定义了如下的函数:

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

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

 这里两个函数都调用了一个main方法,如下:

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);
            }
        }
}

 关键看一下handleNewClient(client)方法的调用,这个是修改类定义的地方,如下:

private static void handleNewClient(final Client client) {
......
inst.addTransformer(client, true);
......
inst.retransformClasses(classes);
}

 这两句话就实现了对现有内存中的类定义的替换,当在一次调用new创建一个新对象时就会使用新的类定义,而老的已经生成的类对象是不会收到干扰的。

那又是谁取执行了对类定义的修改呢,这个是由BTrace脚本解析引擎 + ASM来实现的,脚本引擎负责解析我们所写的脚本,而ASM来对JAVA的字节码进行增强修改。你在Btrace的com.sun.btrace.agent.Client中可以看到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);
......
    }

 现在我们在回顾一下整个流程,用Attach API附加*.jar然后使用BTrace脚本解析引擎 + ASM来实现对类的修改,在使用Instumentation实现类的内存替换,完毕!perfect!BTrace原来也就这么回事,但是我们不得不佩服开发团队的思维和整合能力,向牛人致敬!

分享到:
评论

相关推荐

    BTrace测试

    BTrace测试,参考:http://learnworld.iteye.com/blog/1402763

    BTrace实现原理

    BTrace整个实现的原理是Java Agent+ASM+Java instrument+ Java Complier Api

    BTrace二三事之二:OnMethod子类匹配BUG(怀疑)

    NULL 博文链接:https://sswh.iteye.com/blog/1820391

    btrace release-1.2.5.1

    btrace btrace btrace btrace

    btrace工具

    Btrace:java性能调优及问题追踪工具 Btrace:java性能调优及问题追踪工具

    btrace扩展功能工具

    1.btrace扩展是在btrace已由功能上进行的扩展,原有功能和使用方式依然没变。目前版本扩展了两个功能:接口时间监控和接口时间调用树监控。扩展之后的btrace功能使用时都不需要写btrace脚本。 2.使用接口时间监控...

    BTrace安装包 btrace-bin-1.3.11.3.zip + btrace-src-1.3.11.3.zip

    linux和windows通用,1.3.11...BTrace是一种安全,动态的Java跟踪工具。BTrace通过动态(字节码)检测正在运行的Java程序的类来工作。BTrace将跟踪操作插入到正在运行的Java程序的类中,并对跟踪的程序类进行热交换。

    btrace1.3.9.zip

    btrace1.3.9 jdk1.8 maven 编译构建 http://github.com/btraceio/btrace

    btrace-demo:demo项目

    btrace-demo 示范项目

    jdk1.8-Btrace.rar

    java 在线检测插件Btrace, 无需重启服务,即可在线定位问题

    btrace1.3.9

    btrace1.3.9最新版本转过来

    btrace api 1.2.chm

    btrace api 1.2 文档,从网上扒下来自己做的,其他地方貌似都没有...btrace是一个跟踪、监控java程序的小工具,能够在不改变源代码的情况下监控很多东西,比如:方法运行时间、输入输出参数、抛出的异常、调用的次数等

    BTrace监控远程服务器使用实例

    自己做的BTrace监控,Linux服务器上的tomcat工程,压缩包包含BTrace开发所需的jar包 BTrace简单示例代码 jvisualvm.exe如果远程服务器监控JVM虚拟机信息

    BTrace-一个用于Java平台的安全动态的跟踪工具

    BTrace可用于动态跟踪正在运行的Java程序(类似于DTrace for OpenSolaris应用程序)。 BTrace动态地测试目标应用程序的类以注入跟踪代码(“字节代码跟踪”)。

    jvisualvm-btrace离线安装包

    jvisualvm-btrace离线安装包。 jvisualvm btrace插件离线安装包1.2.85版本,目前官网不支持国内在线下载。 含相关依赖包:...安装时点工具-插件-已下载,点添加插件一次性将4个插件都添加进去,再点安装即可。

    btrace安装包

    btrace安装包,linux和windows通用,1.3.9版本。可以直接解压缩配置环境变量后运行使用

    Btrace 官方zip包

    Btrace用来做项目检测,访问过的类方法统计,无侵略性,JDK1.6

    jvisualvm btrace插件离线安装

    jvisualvm btrace插件离线安装,如果jvisualvm不能安装btrace,则可进行离线安装。 这里收集了安装btrace所需要的依赖包,直接添加 即可安装

    btrace-release-1.3.11.3.zip

    Btrace Java 发布版本,Java 虚拟机监控程序

Global site tag (gtag.js) - Google Analytics