字节码插桩 (Instrumentation)
字节码插桩(Bytecode Instrumentation)是指在编译期,将 Java/Kotlin 类编译成 .class 文件后,但在打包进 APK 前,动态修改其指令。
1. 为什么需要插桩?
- 无痕埋点: 自动在每个
onClick方法里加入日志统计代码。 - 性能监控: 自动在方法开始和结束处记录耗时。
- 修复第三方库 Bug: 在无法获取第三方源码时,直接修改其字节码。
2. 现代方案:AsmClassVisitorFactory
在 AGP 7.0+ 中,官方推出了 AsmClassVisitorFactory 替代了性能低下的 Transform API。
实现步骤
定义 Factory:
kotlinabstract class MyInstrumentationFactory : AsmClassVisitorFactory<InstrumentationParameters.None> { override fun createClassVisitor(classContext: ClassData, next: ClassVisitor): ClassVisitor { // 返回你的自定义 ASM ClassVisitor return MyClassVisitor(next) } override fun isInstrumentable(classData: ClassData): Boolean { // 过滤哪些类需要处理 return classData.className.startsWith("com.myapp") } }在插件中注册:
kotlinandroidComponents { onVariants { variant -> variant.instrumentation.transformClassesWith( MyInstrumentationFactory::class.java, InstrumentationScope.ALL ) {} variant.instrumentation.setAsmFramesComputationMode( FramesComputationMode.COPY_FRAMES ) } }
3. 注意事项
- 性能开销: 插桩会显著增加编译耗时。
- 调试困难: 修改后的代码与源码不一致,调试时可能会看到错乱的堆栈信息。
- ASM 门槛: 你需要掌握底层的 JVM 指令(如
ALOAD,INVOKEVIRTUAL等)。
工具推荐
建议在开发插桩插件时,使用 ASM Bytecode Viewer 插件,实时观察修改前后的字节码差异。