承接上文:
Android 编译优化探索
再最初的版本中需要编译kotlin才能实现Hack自定义增量,但是还一个任务同样也及其耗时org.gradle.api.tasks.compile.JavaCompile,但是此任务不在kotlin插件,难道我们又要自己编译java插件?就连鄙人导师都觉得编译kotlin插件很麻烦。于是乎最后决定采用动态修改字节码的方式实现。作者使用javassist作为字节码编辑器。
JavaCompile创建流程在android工程中JavaCompile的创建是由AGP插件创建,其核心创建核心流程如下
//TaskFactoryUtils.kt funTaskContainer.registerTask( creationAction: TaskCreationAction , secondaryPreConfigAction: PreConfigAction? = null, secondaryAction: TaskConfigAction ? = null, secondaryProviderCallback: TaskProviderCallback ? = null ): TaskProvider { val actionWrapper = TaskAction(creationAction, secondaryPreConfigAction, secondaryAction, secondaryProviderCallback) //调用register注册一个task,第一个参数task名字,第二个参数task类型,第三参数注入构造参数 //这里的creationAction是JavaCompileCreationAction //creationAction.name 任务名字根据变体变化 比如tiya变体就为compileTiyaDebugJavaWithJavac //creationAction.type返回的一个class类型:JavaCompile::class.java return this.register(creationAction.name, creationAction.type, actionWrapper) .also { provider -> actionWrapper.postRegisterHook(provider) } }
我们最后看看这个
class JavaCompileCreationAction( private val variantScope: VariantScope, private val processAnnotationsTaskCreated: Boolean ) : TaskCreationAction() { //...略 override val name: String get() = variantScope.getTaskName("compile", "JavaWithJavac") override val type: Class get() = JavaCompile::class.java //...略 }
知道大致流程我就可以根据如下思想进行 *** 作:
- 将JavaCompileCreationAction的type替换成自己的JavaCompile类即可
class JavaCompileCreationAction( private val variantScope: VariantScope, private val processAnnotationsTaskCreated: Boolean ) : TaskCreationAction() { //...略 //替换为HackJavaCompile override val type: Class get() = HackJavaCompile::class.java //...略 }
- 抢在gradle的默认的类加载器之前修改类并强行加载(双亲委托知识)
因次插件会在根工程之后直接启用。
- 处理父加载器引用子加载器的类问题
这个问题也是比较头疼的一个地方,在起初使用jdbc那样委托当前线程的类加载器去加载,然后通过反射去调用子类函数,但是最后发现当前线程类加载器居然是一个较为顶层的类加载器。最后采用所有引用的类都交付顶层类加载器加载,并禁使用lambda表达式(编译器会创建一个新的类,并用子类加载器加载)。
最后解决办法
如以下伪代码
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)