很早之前就想深入的研究和學(xué)習(xí)一下熱修復(fù)暇检,由于時間的原因一直拖著涉枫,現(xiàn)在才執(zhí)筆弄起來梧田。
Android而更新系列:
Android熱更新一:JAVA的類加載機制
Android熱更新二:理解Java反射
Android熱更新三:Android類加載機制
Android熱更新四:熱修復(fù)機制
Android熱更新五:四大熱修復(fù)方案分析
Android熱更新六:Qzone熱更新原理
Android熱更新七:Tinker熱更新原理
Android熱更新八:AndFix熱更新原理
Android熱更新九:Robust熱更新原理
Android熱更新十:自己寫一個Android熱修復(fù)
微信針對QQ空間超級補丁技術(shù)的不足提出了一個提供DEX差量包萌业,整體替換DEX的方案蔚袍。主要的原理是與QQ空間超級補丁技術(shù)基本相同乡范,區(qū)別在于不再將patch.dex增加到elements數(shù)組中,而是差量的方式給出patch.dex啤咽,然后將patch.dex與應(yīng)用的classes.dex合并晋辆,然后整體替換掉舊的DEX文件,以達到修復(fù)的目的宇整。
我們來逆向微信的APK看一下具體的實現(xiàn):
先找到應(yīng)用入口TinkerApplication
瓶佳,在onBaseContextAttached()
調(diào)用了loadTinker()
,
進入TinkerLoader的tryLoad()方法中,
從方法名可以預(yù)見鳞青,在tryLoadPatchFilesInternal()中嘗試加載本地的補丁霸饲,再經(jīng)過跳轉(zhuǎn)進入核心修復(fù)功能類SystemClassLoaderAdder.class中。
代碼中可以看出臂拓,根據(jù)Android版本的不同贴彼,分別采取具體的修復(fù)操作,不過原理都是一樣的埃儿。我們以V19為例器仗,
從代碼中可以看到,通過反射操作得到PathClassLoader的DexPatchList,反射調(diào)用patchlist的makeDexElements()方法吧本地的dex文件直接替換到Element[]數(shù)組中去童番,達到修復(fù)的目的精钮。
對于如何進行patch.dex與classes.dex的合并操作,這里微信開啟了一個新的進程剃斧,開啟新進程的服務(wù)TinkerPatchService進行合并轨香。
整體的流程如下:
從流程圖來看,同樣可以很明顯的找到這種方式的特點:
優(yōu)勢:
合成整包幼东,不用在構(gòu)造函數(shù)插入代碼臂容,防止verify,verify和opt在編譯期間就已經(jīng)完成根蟹,不會在運行期間進行脓杉。
性能提高。兼容性和穩(wěn)定性比較高简逮。
開發(fā)者透明球散,不需要對包進行額外處理。
不足:
與超級補丁技術(shù)一樣散庶,不支持即時生效蕉堰,必須通過重啟應(yīng)用的方式才能生效凌净。
需要給應(yīng)用開啟新的進程才能進行合并,并且很容易因為內(nèi)存消耗等原因合并失敗屋讶。
合并時占用額外磁盤空間冰寻,對于多DEX的應(yīng)用來說,如果修改了多個DEX文件皿渗,就需要下發(fā)多個patch.dex與對應(yīng)的classes.dex進行合并操作時這種情況會更嚴(yán)重性雄,因此合并過程的失敗率也會更高。