Sophix相關書籍
深入探索Android熱修復技術原理這本書主要講解了Android的熱修復中的熱部署,冷部署以及資源和so庫的修復技巧。全文主要講Sophix應對以上四個方面的技術解析,不管是自家產品還是業界其他方案的橫縱對比,Sophix技術目前都是最優的。
- 補丁小,合成不占太多空間和性能。
- 對代碼的侵入小,對native代碼的hook也精簡,做到最大兼容。
- 支持的修復范圍廣。支持小范圍的即時生效和大范圍的冷啟動。也支持so庫和資源修復。
Hook技術
在事件分發流中,通過Hook鉤子在事件傳送到終點前截獲并監控事件的傳輸,從而處理一些特定干預事件。
- Java API Hook
通過對Android平臺的虛擬機注入與Java反射的方式,來改變Android虛擬機調用函數的方式(ClassLoader),從而達到Java函數重定向的目的。參考
Sophix不同之處
Sophix同時使用了熱啟動的底層替換方案及冷啟動的類加載方案,兩個方案使用的補丁是相同的。優先熱啟動。
代碼修復方案
底層替換方案
- 原理:在已經加載的類中直接替換掉原有方法,是在原有類的結構基礎上進行修改的。在hook方法入口ArtMethod時,通過構造一個新的ArtMethod實現替換方法入口的跳轉。
- 應用:能即時生效,Andfix采用此方案。
- 缺點:底層替換穩定性不好,適用范圍存在限制,通過改造代碼繞過限制既不優雅也不方便,并且還沒提供資源及so的修復。
類加載方案
原理:讓app重新啟動后讓ClassLoader去加載新的類。如果不重啟,原來的類還在虛擬機中無法重復加載。
優點:修復范圍廣,限制少。
應用:騰訊系包括QQ空間,手QFix,Tinker采用此方案。
QQ空間會侵入打包流程。
QFix需要獲取底層虛擬機的函數,不穩定。
Tinker是完整的全量dex加載。
dex的大小占整個apk比例較低,一個app里的dex文件大小不是主要部分,占空間大的主要是資源文件。
QQ空間的插樁原理
將一個單獨無關版主類放到一個單獨的dex中,原dex中所有類的構造函數都引用這個類,一般的實現方法都是侵入dex打包流程,利用.class字節碼修改技術,在所有.class文件的構造函數中引用這個幫助類。-
Tinker與Sophix方案不同之處
Tinker采用dex merge生成全量DEX方案。反編譯為smali,然后新apk跟基線apk進行差異對比,最后得到補丁包。
Dalvik下Sophix和Tinker相同,在Art下,Sophix不需要做dex merge,因為Art下本質上虛擬機已經支持多dex的加載,要做的僅僅是把補丁dex作為主dex(classes.dex)加載而已:
將補丁dex命名為classes.dex,原apk中的dex依次命名為classes(2, 3, 4...).dex就好了,然后一起打包為一個壓縮文件。然后DexFile.loadDex得到DexFile對象,最后把該DexFile對象整個替換舊的dexElements數組就好了。
Tinker與Sophix方案不同點
DexFile.loadDex流程
DexFile.loadDex嘗試把一個dex文件解析并加載到native內存,在加載到native內存之前,如果dex不存在對應的odex,那么Dalvik下會執行dexopt,Art下會執行dexoat,最后得到的都是一個優化后的odex。實際上最后虛擬機上執行的是這個odex而不是dex。
dexopt流程
資源修復方案
基本參考InstantRun的實現:構造一個包含所有新資源的新的AssetManager。并在所有之前引用到原來的AssetManager通過反射替換掉。
Sophix不修改AssetManager的引用,構造的補丁包中只包含有新增或有修改變動的資源,在原AssetManager中addAssetPath這個包就可以了。資源包不需要在運行時合成完整包。
so庫修復方案
本質是對native方法的修復和替換。類似類修復反射注入方式,將補丁so庫的路徑插入到nativeLibraryDirectories數據最前面。
熱修復主流框架對比可查閱
Android熱修復主流框架調研