天天看點

Android熱修複原理

一. AndFix

AndFix的原理就是方法的替換,把有bug的方法替換成更新檔檔案中的方法。

注:在Native層使用指針替換的方式替換bug方法,已達到修複bug的目的。

AndFix采用native hook的方式,這套方案直接使用dalvik_replaceMethod替換class中方法的實作。由于它并沒有整體替換class, 而field在class中的相對位址在class加載時已确定,是以AndFix無法支援新增或者删除filed的情況(通過替換init與clinit隻可以修改field的數值)。Andfix可以支援的更新檔場景相對有限,僅僅可以使用它來修複特定問題。

二. QZone(插樁方式)

該方案基于的是android dex分包方案的, 簡單的概括一下,就是把多個dex檔案塞入到app的classloader之中,但是android dex拆包方案中的類是沒有重複的,如果classes.dex和classes1.dex中有重複的類,當用到這個重複的類的時候,系統會選擇哪個類進行加載呢?  讓我們來看看類加載的代碼:

Android熱修複原理

一個ClassLoader可以包含多個dex檔案,每個dex檔案是一個Element,多個dex檔案排列成一個有序的數組dexElements,當找類的時候,會按順序周遊dex檔案,然後從目前周遊的dex檔案中找類,如果找類則傳回,如果找不到從下一個dex檔案繼續查找。

理論上,如果在不同的dex中有相同的類存在,那麼會優先選擇排在前面的dex檔案的類,如下圖:

Android熱修複原理

在此基礎上,我們構想了熱更新檔的方案,把有問題的類打包到一個dex(patch.dex)中去,然後把這個dex插入到Elements的最前面,如下圖:

Android熱修複原理

三. 微信Tinker(差量包)

Instant Run的冷插拔與buck的exopackage或許能給我們靈感,它們的思想都是全量替換新的Dex。

我們可以将新舊兩個Dex的差異放到更新檔包中,最簡單我們可以采用BsDiff算法。

簡單來說,在編譯時通過新舊兩個Dex生成差異path.dex。在運作時,将差異patch.dex重新跟原始安裝包的舊Dex還原為新的Dex。這個過程可能比較耗費時間與記憶體,是以我們是單獨放在一個背景程序:patch中。為了更新檔包盡量的小,微信自研了DexDiff算法,它深度利用Dex的格式來減少差異的大小。

四、阿裡Sophix

Android熱修複原理

Andfix底層ArtMethod結構時采用内部變量一一替換,倒是這個各個廠商是會修改的,是以相容性不好。

Android熱修複原理

Sophix改變了一下思路,采用整體替換方法結構,忽略底層實作,進而解決相容穩定性問題。

QQ和Tinker的缺陷

Android熱修複原理

Sophix對dex的解決方案

Dalvik下采用阿裡自研的全量dex方案:不是考慮把更新檔包的dex插到所有dex前面(dex插樁),而是想辦法在原理的dex中删除(隻是删除了類的定義)更新檔dex中存在的類,這樣讓系統查找類的時候在原來的dex中找不到,那麼隻有更新檔中的dex加載到系統中,系統自然就會從更新檔包中找到對應的類。

Art下本質上虛拟機以及支援多dex的加載,Sophix的做法僅僅是把更新檔dex作為主dex(classes.dex)而已,相當于重新組織了所有的dex檔案:把更新檔包的dex改名為classes.dex,以前apk的所有dex依次改為classes2.dex、classes3.dex ... classesx.dex,如下圖所示。

Android熱修複原理

常用方案(Instant Run技術):這種方案的相容問題在于替換AssetManager的地方

Android熱修複原理

Sophix資源修複方案

Android熱修複原理
Android熱修複原理

繼續閱讀