前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BTrace实现原理

BTrace实现原理

作者头像
十毛
发布2019-03-27 14:38:45
1.1K0
发布2019-03-27 14:38:45
举报

BTrace是每个Java程序员必备的瑞士军刀,可以实现线上服务器不重启增加调试信息。本文简单介绍一下其实现原理。

BTrace工作原理

BTrace是基于动态字节码修改技术(Hotswap)来实现运行时java程序的跟踪和替换。大体的原理可以用下面的公式描述:

代码语言:javascript
复制
Client(Java compile api + attach api) + Agent(脚本解析引擎 + ASM + Instumentation) + Socket

BTrace工作序列图

BTrace工作序列图

Java Compile API

BTrace使用Compile API把用户编写的源码文件编译成字节码文件

在 JDK 6 中,类库通过 javax.tools 包提供了程序运行时调用编译器的 API。

代码语言:javascript
复制
public class Compiler {
    public static void main(String[] args) throws Exception {
        String fullQuanlifiedFileName = "compile" + java.io.File.separator + "Target.java";
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        FileOutputStream err = new FileOutputStream("err.txt");
        int compilationResult = compiler.run(null, null, err, fullQuanlifiedFileName);
        if (compilationResult == 0) {
            System.out.println("Done");
        } else {
            System.out.println("Fail");
        }
    }
}

Java Attach API

BTrace使用Attach API把BTrace Agent附加到待调试的JVM上去

Attach API不是Java的标准API,而是Sun公司提供的一套扩展API,用来向目标JVM"附着"(Attach)代理工具程序的。有了它,开发者可以方便的监控一个JVM,运行一个外加的代理程序,Sun JVM Attach API功能上非常简单,仅提供了如下几个功能:

  1. 列出当前所有的JVM实例描述
  2. Attach到其中一个JVM上,建立通信管道
  3. 让目标JVM加载Agent

ASM

BTrace使用ASM修改当前类,附加调试信息,得到新的类

我们都知道,一般情况下,Class文件是通过javac编译器产生的,然后通过类加载器加载到虚拟机内,再通过执行引擎去执行。现在我们可以通过ASM的API直接生成符合Java虚拟机规范的Class字节流,这样,ASM做的事情一定程度上正是javac解释器做的工作。

可以说ASM分析一个类、从字节码角度创建一个类、修改一个已经被编译过的类文件。

Instrumentation

BTrace使用JVM Instrumentation动态替换当前类

利用 Java 代码,即 java.lang.instrument 做动态 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能从本地代码中解放出来,使之可以用 Java 代码的方式解决问题。使用 Instrumentation,开发者可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义。有了这样的功能,开发者就可以实现更为灵活的运行时虚拟机监控和 Java 类操作了,这样的特性实际上提供了一种虚拟机级别支持的 AOP 实现方式,使得开发者无需对 JDK 做任何升级和改动,就可以实现某些 AOP 的功能了。

关键逻辑

BTrace的入口类在https://github.com/btraceio/btrace/blob/master/src/share/classes/com/sun/btrace/client/Main.java中。在其main方法中,可以看到起最终的核心逻辑是在https://github.com/btraceio/btrace/blob/master/src/share/classes/com/sun/btrace/client/Client.java中。方法调用如下:

  • client.compile
  • client.attach
  • client.submit

核心流程代码如下:

代码语言:javascript
复制
try {
    Client client = new Client(port, OUTPUT_FILE, PROBE_DESC_PATH,
        DEBUG, TRACK_RETRANSFORM, TRUSTED, DUMP_CLASSES, DUMP_DIR, statsdDef);
    if (! new File(fileName).exists()) {
        errorExit("File not found: " + fileName, 1);
    }
    //编译Java源码
    byte[] code = client.compile(fileName, classPath, includePath);
    if (code == null) {
        errorExit("BTrace compilation failed", 1);
    }
    if (!hostDefined)
        //调用JVM的Attach API,在被调试JVM中attach一个Agent
        client.attach(pid, null, classPath);
    registerExitHook(client);
    if (con != null) {
        registerSignalHandler(client);
    }
    if (isDebug()) debugPrint("submitting the BTrace program");
    //提交调试代码(被调试JVM中的Agent收到代码后使用ASM修改类定义)
    client.submit(host, fileName, code, btraceArgs, createCommandListener(client));
} catch (IOException exp) {
    errorExit(exp.getMessage(), 1);
}

BTrace系列

参考

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.12.22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • BTrace工作原理
    • BTrace工作序列图
      • Java Compile API
        • Java Attach API
          • ASM
            • Instrumentation
              • 关键逻辑
              • BTrace系列
              • 参考
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档