ASM字节码插桩

什么是插桩

QQ空间曾经发布的_热修复解决方案_中利用 Javaassist 库实现向类的构造函数中插入一段代码解决 CLASS_ISPREVERIFIED 问题。包括了 Instant Run 的实现以及参照 Instant Run 实现的热修复美团 Robus 等,都利用到了插桩技术。

插桩就是将一段代码插入到另一段代码,或替换另一段代码。字节码插桩顾名思义就是在我们编写的源码编译成字节码(Class)后,在Android下生成 dex 之前修改 Class 文件,修改或者增强原有代码逻辑的操作。

字节码操作框架

上面我们提到QQ空间使用了 Javaassist 来进行字节码插桩,除了 Javaassist 之外还有一个应用更为广泛的 ASM 框架同样也是字节码操作框架,Instant Run 包括 AspectJ 就是借助 ASM 来实现各自的功能。

我们非常熟悉的JSON格式数据是基于文本的,我们只需要知道它的规则就能够轻松的生成、修改JSON数据。同样的Class字节码也有其自己的规则(格式)。操作JSON可以借助GSON来非常方便的生成、修改JSON数据。而字节码 Class,同样可以借助Javassist/ASM来实现对其修改。可能 Javassist 更加简单,而 ASM 性能更好。

字节码操作框架的作用在于生成或者修改Class文件,因此在Android中字节码框架本身是不需要打包进入APK的,只有其生成/修改之后的Class才需要打包进入APK中。它的工作时机在上图Android打包流程中的生成Class之后,打包dex之前。

ASM的使用

由于 ASM 具有相对于 Javassist 更好的性能以及更高的灵活行,我们这篇文章以使用ASM为主。在真正利用到 Android 中之前,我们可以先在 Java 程序中完成对字节码的修改测试。

// …