ByteX字節(jié)碼插件開發(fā)平臺
ByteX 是一個基于 gradle transform api 和 ASM 的字節(jié)碼插件平臺,由字節(jié)跳動抖音 Android 團隊提供。
目前集成了若干個字節(jié)碼插件,每個插件完全獨立,既可以脫離 ByteX 這個宿主而獨立存在,又可以自動集成到宿主和其它插件一起整合為一個單獨的 Transform。插件和插件之間,宿主和插件之間的代碼是完全解耦的(有點像組件化),這使得ByteX在代碼上擁有很好的可拓展性,新插件的開發(fā)將會變得更加簡單高效。
背景
如果所有feature都開發(fā)一個單獨的插件,每個插件編譯構建耗時+10s,各個插件疊在一起,編譯耗時就會呈線性增長;那如果我們所有feature都基于一個現成的字節(jié)碼插件做迭代開發(fā),又會讓插件代碼變得越來越臃腫,代碼耦合嚴重。所以就有了這個想法,單獨做一個字節(jié)碼插件開發(fā)平臺,新的feature可以基于它做擴展。
特點
-
代碼復用。公共的代碼下沉下到common,給所有插件復用,這樣每個插件就只需要專注于字節(jié)碼插樁就行了。
-
插件間代碼隔離,相互解耦。之前字節(jié)碼的相關feature都是基于某個字節(jié)碼插件module來迭代擴展的,但各個feature的代碼耦合在一起,久而久之這個插件module就成為了大雜燴。而基于ByteX,各個feature都獨立成一個個插件,各個feature的代碼相互隔離,相互獨立,有利于新插件的功能拓展。
-
平臺化讓transform更高效。
-
class文件多線程并發(fā)處理,充分利用打包機的CPU資源。
-
插件間自動無縫地整合成一個Transform,提高處理構建的效率。Transform過程中,對class文件的IO是比較耗時的,把所有的plugin整合成一個單獨transform可以避免打包的額外時間開銷呈線性增長。讓耗時從1+1=2,變成1+1<2或者約等于1。
-
-
插件移植性強。每個插件都可以脫離ByteX宿主,獨立成一個transform,獨立工作。
項目結構
TransformEngine
負責遍歷讀取工程和Android SDK里的所有class文件,并回寫到transform指定目錄。
base-plugin
宿主,也就一個殼。
common
基礎代碼庫,包括類圖構建邏輯,日志,提供給各個插件的適配接口等。
其它插件module
依賴common,實現相應的接口和各自的字節(jié)碼插樁邏輯。
快速接入
在build.gradle里添加以下配置,按需apply你的插件:
buildscript {
ext.plugin_version="0.3.0"
repositories {
google()
jcenter()
maven {
url "https://artifact.bytedance.com/repository/byteX/"
}
}
dependencies {
classpath "com.bytedance.android.byteX:base-plugin:${plugin_version}"
// Add bytex plugins' dependencies on demand. 按需添加插件依賴
classpath "com.bytedance.android.byteX:refer-check-plugin:${plugin_version}"
// ...
}
}
apply plugin: 'com.android.application'
// apply ByteX宿主
apply plugin: 'bytex'
ByteX {
enable true
enableInDebug false
logLevel "DEBUG"
}
// 按需apply bytex 插件
apply plugin: 'bytex.refer_check'
// ...
注意:如果不apply ByteX宿主,那么這些ByteX插件與普通的插件無異,將會各自形成單獨的Transform。反之,所有ByteX的插件將會自動融合成一個Transform。
以下是基于ByteX開發(fā)的插件,可以進入各個插件的README.md了解插件的接入方式。
已集成的插件
- access-inline-plugin(access方法內聯)
- shrink-r-plugin(R文件瘦身和無用資源檢查)
- closeable-check-plugin(文件流的close檢查)
- const-inline-plugin(常量內聯)
- field-assign-opt-plugin(優(yōu)化多余賦值指令)
- getter-setter-inline-plugin (getter和setter方法內聯)
- method-call-opt-plugin(干凈地刪除某些方法調用,如
Log.d) - coverage-plugin(線上代碼覆蓋率)
- refer-check-plugin(檢查是否有調用不存在的方法和引用不存在的字段)
- serialization-check-plugin(序列化檢查)
- SourceFileKiller(刪除SourceFile和行號屬性,作為示例)
- ButterKnifeChecker(檢測跨module使用ButterKnife可能導致的問題)
- RFileKnife(修復R.java太大編譯報code too large的問題)
