1. Dex修復(fù)
Dex修復(fù)分為熱部署底層熱替換與冷部署重啟
1.1 熱部署底層替換
直接在native虛擬機(jī)層替換原有方法,是在原來類的基礎(chǔ)上進(jìn)行修改矮固。
AndFix:將native虛擬機(jī)層原有的Method結(jié)構(gòu)的所有成員變量替換成新函數(shù)Method結(jié)構(gòu)的成員另患。
Sophix:將native虛擬機(jī)層原有的Method結(jié)構(gòu)整體進(jìn)行替換呆瞻。
不適用的情況:
- 引起原有類中發(fā)生結(jié)構(gòu)變化的修改
- 修復(fù)的非靜態(tài)方法會被反射調(diào)用
1.2 冷部署重啟
DexClassLoader -> DexPathList -> DexFile -> -> Element ->
dexElements.add(element)
當(dāng)類的所有方法直接引用到的類(第一層級關(guān)系)和該類在同一個(gè)dex文件中時(shí)彩匕,類校驗(yàn)dvmVerifyClass就會返回true墓造,類的accessFlags在虛擬機(jī)層會被設(shè)置CLASS_PREVERIFIED已校驗(yàn)標(biāo)志柴我。
如果類沒被設(shè)置CLASS_PREVERIFIED解寝,那么類的Verify操作都將在類的初始化進(jìn)行。而類的Verify僅僅是在apk第一次安裝執(zhí)行dexopt的時(shí)候進(jìn)行艘儒,但類的Verify會對類所有方法的指令都進(jìn)行校驗(yàn)聋伦,是個(gè)稍重的過程,當(dāng)加載的類多的時(shí)界睁,整個(gè)Dex的加載過程耗時(shí)較大觉增,所以插樁給類加載效率帶來較大的影響。
2. 資源修復(fù)
2.1 Instant Run
- 構(gòu)造加載了補(bǔ)丁資源的新AssetManager替換原有的AssetManager
- 將原有代碼中所有引用到舊AssetManager的地方修改為新AssetManager
2.2 Sophix
構(gòu)造一個(gè)package id不為0x7f的補(bǔ)丁資源包晕窑,此包只包含原有包中發(fā)生改變的資源以及新增的資源抑片,然后在原有AssetManager的基礎(chǔ)上,反射調(diào)用addAssetPath方法將補(bǔ)丁資源寶加載進(jìn)去杨赤。
3. SO庫修復(fù)
3.1 SO實(shí)時(shí)生效
1.Dalvik虛擬機(jī)下動態(tài)注冊的native方法需實(shí)時(shí)修復(fù)敞斋,必須對so文件改名
2.靜態(tài)注冊的native方法的實(shí)時(shí)修復(fù),因?yàn)闊o法得知so庫中哪些native方法發(fā)生了變更疾牲,很難做到修復(fù)
3.對于新增動態(tài)注冊的native方法植捎,需在dex中增加相應(yīng)的Java方法,否則加載so文件時(shí)報(bào)NoSuchMethodError阳柔,而增加Java方法是無法做到實(shí)時(shí)生效熱修復(fù)焰枢,所以so庫新增動態(tài)注冊的native方法也無法做到實(shí)時(shí)生效熱修復(fù)
3.2 SO冷部署重啟生效
1. 通常的冷啟動
用自己實(shí)現(xiàn)的加載SO庫的接口替換System默認(rèn)的加載SO庫的接口。
2. Sophix的冷啟動
反射注入方式將補(bǔ)丁SO插入到nativeLibraryDirectories/nativeLibraryPathElements數(shù)組的最前面舌剂,達(dá)到優(yōu)先加載補(bǔ)丁SO的目的济锄,從而實(shí)現(xiàn)SO修復(fù)。