1. Dex修復
Dex修復分為熱部署底層熱替換與冷部署重啟
1.1 熱部署底層替換
直接在native虛擬機器層替換原有方法,是在原來類的基礎上進行修改。
AndFix:將native虛擬機器層原有的Method結構的所有成員變數替換成新函式Method結構的成員。
Sophix:將native虛擬機器層原有的Method結構整體進行替換。
不適用的情況:
- 引起原有類中發生結構變化的修改
- 修復的非靜態方法會被反射呼叫
1.2 冷部署重啟
DexClassLoader -> DexPathList -> DexFile -> -> Element ->
dexElements.add(element)
當類的所有方法直接引用到的類(第一層級關係)和該類在同一個dex檔案中時,類校驗dvmVerifyClass就會返回true,類的accessFlags在虛擬機器層會被設定CLASS_PREVERIFIED已校驗標誌。
如果類沒被設定CLASS_PREVERIFIED,那麼類的Verify操作都將在類的初始化進行。而類的Verify僅僅是在apk第一次安裝執行dexopt的時候進行,但類的Verify會對類所有方法的指令都進行校驗,是個稍重的過程,當載入的類多的時,整個Dex的載入過程耗時較大,所以插樁給類載入效率帶來較大的影響。
2. 資源修復
2.1 Instant Run
- 構造載入了補丁資源的新AssetManager替換原有的AssetManager
- 將原有程式碼中所有引用到舊AssetManager的地方修改為新AssetManager
2.2 Sophix
構造一個package id不為0x7f的補丁資源包,此包只包含原有包中發生改變的資源以及新增的資源,然後在原有AssetManager的基礎上,反射呼叫addAssetPath方法將補丁資源寶載入進去。
3. SO庫修復
3.1 SO實時生效
1.Dalvik虛擬機器下動態註冊的native方法需實時修復,必須對so檔案改名
2.靜態註冊的native方法的實時修復,因為無法得知so庫中哪些native方法發生了變更,很難做到修復
3.對於新增動態註冊的native方法,需在dex中增加相應的Java方法,否則載入so檔案時報NoSuchMethodError,而增加Java方法是無法做到實時生效熱修復,所以so庫新增動態註冊的native方法也無法做到實時生效熱修復
3.2 SO冷部署重啟生效
1. 通常的冷啟動
用自己實現的載入SO庫的介面替換System預設的載入SO庫的介面。
2. Sophix的冷啟動
反射注入方式將補丁SO插入到nativeLibraryDirectories/nativeLibraryPathElements陣列的最前面,達到優先載入補丁SO的目的,從而實現SO修復。