本文有对其他博客的一些借鉴。
我们都知道Dalvik虚拟机运行的是.dex文件。.dex文件又是通过.class文件通过dx工具编译而来。今天要体验的就是一个非常有意思的技术,字节码的插桩。
大部分时候都会用埋点来介绍这个技术。原理就是,通过Transform这个类去获取项目中的.class文件。然后使用AMS提供的几个类去解析.class文件。通过对类名,方法名的判断,筛选出你需要修改的.class文件。然后在需要修改的地方插入你想要的被转成字节码的代码。
最复杂的部分是:.class文件有着自己很严格的格式,如果我们想注入代码时,不是直接插入相关的指令即可。我们还需要去找到相应的StackMapFrame,换句话说就是要找到对应的帧栈,因为我们插入的方法可能和已有的方法中的对象有引用关系,所以需要对帧栈进行计算,最后还要压缩剩下的帧。不过好在这步AMS已经处理完了,我们只需要进行调用就行。
首先要使用使用Transform就需要使用自定义插件。那么先去自定义一个插件。新建一个android library。把除了src/main/java和.gradle文件外的其他所有文件都删除了。

这样就行了。
然后我们需要用groovy语言去写插件所以需要一个groovy文件夹。在此之前先去把gradle重新写一下。把之前的都删了,然后插入下面的就行,这个写法基本上是固定了。因为我们要把插件发布到本地。
apply plugin: 'groovy'
apply plugin: 'maven'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation gradleApi()
implementation localGroovy()
implementation 'com.android.tools.build:gradle:3.6.1'
//ASM相关依赖
implementation 'org.ow2.asm:asm-commons:7.1'
implementation 'org.ow2.asm:asm:7.1'
}
然后在groovy文件夹下面自己新建一个.groovy文件。用AS编写groovy文件需要相当注意,因为这玩意大部分时候都不会报错。里面的代码意思是将自定义的transform注册到任务里,而且打印了一句话。
package my.test.lifecycle
import com.android.build.gradle.AppExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
class LifeCyclePlugin implements Plugin<Project>{
@Override
void apply(Project project) {
System.out.println("register_LifeCyclePlugin")
def android =project.extensions.getByType(AppExtension);
LifeCycleTransForm lifeCycleTransForm=new LifeCycleTransForm();
android.registerTransform(lifeCycleTransForm)
}
}
然后在main文件夹下在新建一个resources文件夹

文件名一定不能错。在这个文件夹下新建一个.properties文件。my.test.lifecycle前面这段就是你的插件名了。
gradle文件中在写上group与version,然后直接运行uploadArchives这个任务。你会看到在工程下出现一个新的文件夹asm_lifecycle。
group='my.test.lifecycle'
version='1.0.0'
uploadArchives{
repositories

本文深入探讨字节码插桩技术,介绍如何通过Transform类获取并解析.class文件,利用ASM库实现在特定方法前后插入自定义代码,实现监控、插件化等功能。文章详细讲解了自定义插件及Transform的创建过程。
最低0.47元/天 解锁文章
9583

被折叠的 条评论
为什么被折叠?



