一、Booster概览
Booster https://github.com/didi/booster主要由 Transformer 和 Task 组成,Transformer 主要用于对字节码进行扫描或修改(取决于 Transformer 的功能),Task 主要用于构建过程中的资源处理,为了满足特异的优化需求,Booster 提供了 Transformer SPI and VariantProcessor SPI 允许开发者进行定制,以下是 Booster 的整体框架:
二、Booster功能
Performance detection | 性能检测
使用 Booster 可以发现潜在的性能问题,例如,在应用中调用可能阻塞 UI 线程或者主线程的 API,如:I/O API 等。详情请参见: booster-transform-lint。
Performance optimization | 性能优化
对于开发者来说,线程管理一直是个头疼的问题,特别是第三方 SDK 中的线程,过多的线程可能会导致内存不足,然而幸运的是,这些问题都能通过 Booster 来解决。
System bugs fix | 系统问题修复
例如全局性地修复 Android API 25 版本中 Toast 导致的崩溃。详情请参见:booster-transform-toast、booster-transform-shared-preferences.
Package size reduction | 应用瘦身
Such as image resources compression, r inline, etc.
如:资源压缩及冗余资源删除、资源索引内联。
2.1 booster-transform-shared-preferences SharedPreferences 优化
shared-preferences的commit的操作(有返回值),有可能阻塞ui线程。Booster对没有用到返回值的commit操作放到异步线程中,对应Transformer实现如下:
@AutoService(ClassTransformer::class)
class SharedPreferencesEditorTransformer : ClassTransformer {
private lateinit var logger: PrintWriter
override fun onPreTransform(context: TransformContext) {
this.logger = context.reportsDir.file(Build.ARTIFACT).file(context.name).file("report.txt").touch().printWriter()
}
override fun onPostTransform(context: TransformContext) {
this.logger.close()
}
override fun transform(context: TransformContext, klass: ClassNode): ClassNode {
if (klass.name == SHADOW_EDITOR) {
return klass
}
klass.methods.forEach { method ->
method.instructions?.iterator()?.asIterable()?.filterIsInstance(MethodInsnNode::class.java)?.filter {
it.opcode == Opcodes.INVOKEINTERFACE && it.owner == SHARED_PREFERENCES_EDITOR
}?.forEach { invoke ->
when ("${invoke.name}${invoke.desc}") {
"commit()Z" -> if (Opcodes.POP == invoke.next?.opcode) {
// if the return value of commit() does not used
// use asynchronous commit() instead
invoke.optimize(klass, method)
method.instructions.remove(invoke.next)
}
"apply()V" -> invoke.optimize(klass, method)
}
}
}
return klass
}
private fun MethodInsnNode.optimize(klass: ClassNode, method: MethodNode) {
logger.println(" * ${this.owner}.${this.name}${this.desc} => $SHADOW_EDITOR.apply(L$SHARED_PREFERENCES_EDITOR;)V: ${klass.name}.${method.name}${method.desc}")
this.itf = false
this.owner = SHADOW_EDITOR
this.name = "apply"
this.opcode = Opcodes.INVOKESTATIC
this.desc = "(L$SHARED_PREFERENCES_EDITOR;)V"
}
}
private const val SHARED_PREFERENCES_EDITOR = "android/content/SharedPreferences\$Editor"
private const val SHADOW_EDITOR = "com/didiglobal/booster/instrument/ShadowEditor"
public class ShadowEditor {
public static void apply(final SharedPreferences.Editor editor) {
if (Looper.myLooper() == Looper.getMainLooper()) {
AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
editor.commit();
}
});
} else {
editor.commit();
}
}
}
2.2 booster-task-list-permission
本模块用于显示本工程依赖的 AAR 中使用的 Android 权限列表。
三、Booster自定义Transformer
3.1 transformer-with-asm
https://github.com/boostersamples/transformer-with-asm
@AutoService(ClassTransformer::class)
class SampleAsmTransformer : ClassTransformer {
override fun transform(context: TransformContext, klass: ClassNode) = klass.also {
println("Transforming ${klass.className}: ")
klass.fields.ifNotEmpty {
println(klass.fields.joinToString("\n") {
" - " + it.name + ": " + it.desc
})
}
klass.methods.ifNotEmpty {
println(klass.methods.joinToString("\n") {
" - " + it.name + it.desc
})
}
}
}
3.2 transformer-with-javassist
https://github.com/boostersamples/transformer-with-javassist
@AutoService(ClassTransformer::class)
class SampleJavassistTransformer : ClassTransformer {
override fun transform(context: TransformContext, klass: CtClass) = klass.also {
println("Javassist Transforming ${klass.name}: ")
klass.fields.asList().ifNotEmpty {
println(klass.fields.joinToString("\n") {
" - $it"
})
}
klass.methods.asList().ifNotEmpty {
println(klass.methods.joinToString("\n") {
" - ${it.name}${Descriptor.toString(it.signature)}"
})
}
}
}