android asm gradle,Android Gradle Plugin的应用

背景:

1.趋势:目前很多知名框架在后期维护中基于性能优化,代码解耦的考虑都加入Gradle Plugin的技术,如Alibaba的ARouter, 360的Replugin等等。在后期的版本升级后,在性能上都有很大的优化。

2.需求:随着项目中对于APM(Application Performance Management) 越来越关注,后期功能上会加入性能监控,网络请求耗时等一些监控,这个时候为了减少对原业务功能的影响,​达到“无需修改原有结构,无侵入接入”和“无性能损害”的目标,就需要有一种办法在编译阶段自动插入代码实现(运行阶段操作肯定会消耗性能,pass)。那就是传说中的“插桩”,AOP思想(面向切面编程),使用Gradle Plugin 技术。

3.现状:产品经理为了对产品上线之后用户操作数据的统计,每次上线前会对代码中增加埋点。随着功能的庞大和业务的复杂,造成埋点代码越来越多,这些代码在某种程度会影响业务逻辑的阅读。这个时候如果能把埋点代码和业务代码进行分离,只要在编译的时候把埋点代码注入到业务代码就可以了。

概述

Gradle Plugin是Android项目中为了达到优化性能,代码解耦的目标,在编译阶段通过字节码的改变在已存在的类中插入代码,或者创建一个新的类,采用的是AOP面向切面思想编程,接下来以下几个方面进行讲述:

1.Android App的编译过程

2.自定义Gradle Plugin的创建和Transform api的使用

3.使用asm实现字节码插桩

编译过程

64a47b2a00e5

编译过程

上图介绍了一个app是如何编译成在手机上运行的apk,gradle plugin 是在生成.class文件之后,生成.dex之前对字节码进行操作。它其中包含.class 文件和第三方的jar文件,在编译过程中遍历拿到这些文件,然后对需要更改的类文件进行更改。

自定义Gradle-Plugin 插件

1.自定义插件

1.首先引入jar包:

2.0.0以前:compile'com.android.tools.build:transform-api:1.5.0'

2.0.0以后://从2.0.0版本开始就是在gradle-api中

implementation'com.android.tools.build:gradle-api:3.1.4

2.创建自定义插件:

首先创建自定义插件,在自定以插件中注册一个自定义的transform,编写语言可以是groovy,java,kotlin

64a47b2a00e5

Arouter 创建的自定义插件

如上图apply方法中只有在主app中才会需要导入这个插件生成注册的代码。然后创建自定义RegisterTransform 注册到插件中,其中创建了一个集合,赋值给这个插件,这个会在后面讲解。

2自定义transform

1.transform原理及应用

64a47b2a00e5

transform原理

1.每一个transform 是一个Gradle task,TaskMandger 会把Transform 串联起来,第一个 Transform 会把javac编译的class文件,jar包,resource(asset中的资源)接收到,然后进行处理,传送给下一个Transform。

2.自定义的transform会插到系统自带的前面。

3.dexBuilder,dexMerger,mergeJavaRes,mergeJniLibs,proguard 这些常见Transform都属于系统的Transform。

2.transform类详解

64a47b2a00e5

自定义Transform

1.getName:返回插件的名字,这个 name 并不是最终的名字,

格式如:transformClassesWith“name”ForDebug

2.getInputTypes: 获取过滤的类型:

CONTENT_CLASS:表示要处理编译后的字节码,可能是 jar 包也可能是目录

CONTENT_RESOURCES:表示处理标准的 java 资源,在assert文件夹中

3.getScopes:获取过滤的范围

PROJECT: 只处理当前项目

SUB_PROJECTS:只处理子项目

PROJECT_LOCAL_DEPS:只处理当前项目的本地依赖,例如jar, aar

EXTERNAL_LIBRARIES:只处理外部的依赖库

PROVIDED_ONLY:只处理本地或远程以provided形式引入的依赖库

TESTED_CODE:测试代码

4 isIncremental: 当前 Transform 是否支持增量编译

NOTCHANGED: 当前文件不需处理,甚至复制操作都不用;

ADDED、CHANGED: 正常处理,输出给下一个任务;

REMOVED: 移除outputProvider获取路径对应的文件。

5:transform()方法的参数详解

inputs :消费型输入

referencedInputs:引用型输入,无需输出

isIncremental:是否增量更新

outputProvider:管理输出路径

6. transform 的优化:private  WaitableExecutor waitableExecutor;

waitableExecutor =WaitableExecutor.useGlobalSharedThreadPool();

//异步并发处理jar/class

waitableExecutor.execute(()->{

bytecodeWeaver.weaveJar(srcJar,destJar);returnnull;

});

//异步并发处理jar/class

waitableExecutor.execute(()->{

bytecodeWeaver.weaveSingleClassToFile(file,outputFile,inputDirPath);returnnull;

});

//等待所有任务结束

waitableExecutor.waitForTasksWithQuickFail(true);

3.ASM使用

简介:

ASM 可以直接产生二进制的class 文件,也可以在增强既有类的功能。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。

ASM框架中的核心类有以下几个:

ClassReader:该类用来解析编译过的class字节码文件。

ClassWriter:该类用来重新构建编译后的类,比如说修改类名、属性以及方法,甚至可以生成新的类的字节码文件。

ClassVisitor:主要负责 “拜访” 类成员信息。其中包括标记在类上的注解,类的构造方法,类的字段,类的方法,静态代码块。

AdviceAdapter:实现了MethodVisitor接口,主要负责 “拜访” 方法的信息,用来进行具体的方法字节码操作。

64a47b2a00e5

ClassVisitor 实现

64a47b2a00e5

MethodVisitor 实现

总结:Android Gradle Plugin 大概讲到这,最后一步Asm实现可以使用Android studio 插件asm-bytecode-outline,它会生成asm实现代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值