Skip to content

字节码插桩 (Instrumentation)

源:Android Gradle 插件 API

字节码插桩(Bytecode Instrumentation)是指在编译期,将 Java/Kotlin 类编译成 .class 文件后,但在打包进 APK 前,动态修改其指令。

1. 为什么需要插桩?

  • 无痕埋点: 自动在每个 onClick 方法里加入日志统计代码。
  • 性能监控: 自动在方法开始和结束处记录耗时。
  • 修复第三方库 Bug: 在无法获取第三方源码时,直接修改其字节码。

2. 现代方案:AsmClassVisitorFactory

在 AGP 7.0+ 中,官方推出了 AsmClassVisitorFactory 替代了性能低下的 Transform API

实现步骤

  1. 定义 Factory:

    kotlin
    abstract 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")
        }
    }
  2. 在插件中注册:

    kotlin
    androidComponents {
        onVariants { variant ->
            variant.instrumentation.transformClassesWith(
                MyInstrumentationFactory::class.java,
                InstrumentationScope.ALL
            ) {}
            variant.instrumentation.setAsmFramesComputationMode(
                FramesComputationMode.COPY_FRAMES
            )
        }
    }

3. 注意事项

  • 性能开销: 插桩会显著增加编译耗时。
  • 调试困难: 修改后的代码与源码不一致,调试时可能会看到错乱的堆栈信息。
  • ASM 门槛: 你需要掌握底层的 JVM 指令(如 ALOAD, INVOKEVIRTUAL 等)。

工具推荐

建议在开发插桩插件时,使用 ASM Bytecode Viewer 插件,实时观察修改前后的字节码差异。