btrace

Posted by Mr.Cai on June 14, 2018

0x01 demo

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

@BTrace
public class EnterWorldScript {

    //监控某一个方法的执行时间
    @OnMethod(clazz = "a.b.c", method = "process", location=@Location(Kind.RETURN))
    public static void printMethodRunTime(@ProbeClassName String probeClassName, @Duration long duration){
        println(probeClassName + ", duration:" + duration / 1000000 + " ms");
    }

}

1、从github的btrace repo中下载release版本。 2、解压缩,export BRACE_HOME=xxx 3、使用brace jpid EnterWorldScript.java就可以看到a.b.c的process方法的耗时了。

0x02 原理

使用jvmti在运行时attach到java进程上,启动javaagent,使用Instrument来动态的将代码注入到目标代码中。
btrace基本上只可以去打印一些调试信息、日志。下面列出的是btrace禁止的事情,会在remote server上启动的btrace-agent做校验(可以关闭这些校验,不过不安全)。

  • 不能新建类、新建数组、 抛异常、 捕获异常,
  • 不能调用实例方法以及静态方法(com.sun.btrace.BTraceUtils除外)
  • 不能将目标程序和对象赋值给BTrace的实例和静态field
  • 不能定义外部、 内部、匿名、本地类、不能实现接口、 不能扩展类
  • 不能有同步块和方法
  • 不能有循环
  • 不能使用assert语句
  • 不能使用class字面值

0x03 扩展

  • 可以自己写个javaagent,存下Instrument的引用,使用这个引用就可以在运行时动态的修改任何代码了(但是不能对类签名、字段签名、方法签名进行修改,也无法添加字段和方法,这个是JVM TI的限制)。如果使用了这种方法,一定要搭配着iptables规则,最好还有权限校验,防止恶意注入。
  • 阿里的JVM-SANDBOX计划调研下,看看是否可以作为热修复的备选方案。
  • 在内网开发的时候btrace的用途并没有jdwp的用处大,内网开发的时候可以让开发有远程debug的能力,这样在开发效率上会比使用btrace的效率更高。
  • btrace的wiki
  • btrace不能用于howswap的原因