Skip to main content

代码插桩

img.png

什么是代码插桩

百科介绍
代码插桩是实现覆盖测试的关键技术之一,而高效的插桩技术对于嵌入式软件的测试来说又是至关重要的。在对codetest 中插桩技术研究的基础上,以gcc 作为开发平台,应用并实现了新的插桩器,采用增加一个词法语法分析器的方法,提高了插桩的效率。经过实验证明新的插装器具有代码膨胀率小,插桩速度快的优点,在一定程度上做到了高效插桩。

网友介绍
插桩技术指在保证原有程序逻辑完整性的基础上,在程序中插入探针,通过探针采集代码中的信息(方法本身、方法参数值、返回值等)在特定的位置插入代码段,从而收集程序运行时的动态上下文信息。

从Android开发的角度看插桩

img.png

从Android整个开发过程中来看,插桩是发生的编译期,这里表明它两个重要特点:

  1. 插桩是非侵入式的,很多人在集成框架的同时都会考虑到侵入性,而插桩可以说是非侵入式,无需集成到业务代码中
  2. 插桩是灵活的,既然在编译期,就可以根据不同的编译版本,配置不同的插桩,实现插桩自由

插桩会带来什么问题

我相信任何事物都有两面性,不光要看到它的亮点,也要挖掘它的缺点,这样才能正确的做事。那么插桩会带来什么负面的影响么?

  • 性能问题
  • 稳定性问题
  • 编译时间成本增加

性能问题

由于插桩,通常在函数的前后加入了统计代码,导致函数响应时间变长,内存增加,cup使用率同样增加,我们都知道方法内联把,如果代码插桩是插入一个类调用一个函数呢?会不会造成函数调用栈成倍增加呢? 所有说插桩带来的问题,务必会造成一定的性能损耗,这是不可避免的。

稳定性问题

既然是插入了代码,使原有逻辑变复杂了,无形中对稳定性带来了挑战,如果插入的代码有漏洞,就会引发严重的问题,不可小觑。

编译时间成本增加

既然在编译期做了手脚,那么在Gradle编译Class文件后,就需要对所有的Class文件做一次遍历,然后进行插桩操作,有的插桩 还会对Jar包进行解压-插桩-打包操作,所以在编译时间上,是会有明显的消耗的。

插桩有什么原则么

针对插桩带来的问题,我们提出如下原则,来尽量的减少因为插桩带来的问题。

  • 尽可能的实现动态配置,配置需要插桩的类或者函数,甚至是jar包
  • 尽可能的使用方法内联方式,不管什么方法,目的是减少方法栈的激增

在android里面做插桩,需要什么基础能力

  • 打包流程,明白编译过程
  • gradle插件开发,实现无侵入式的第一步
  • ASM,实现字节码插桩的框架
  • 字节码,也就是Class文件,因为操作的都是Class文件,所以需要增删改的是字节码格式,所以要懂,不过,有个好消息是现在有IDE插件,可以将代码转换成ASM格式的插桩代码。缩减了学习成本。 但话又说回来,如果你不理解字节码的话,可能遇到了问题就很麻烦,毕竟IDE插件不是万能的,如果已经几年没升级了,而你的ASM已经升级了N个版本,也是会有问题的,请多注意。