android热修复原理底层替换,Android 热修复 - 各框架原理学习及对比
寫在開頭
從15年開始各技術(shù)大佬們開始研究熱修復(fù)技術(shù),并陸續(xù)開源了許多的熱修復(fù)框架。如 Jasonross 的 Nuwa,美團的 Robust,阿里的 Andfix,騰訊的 Tinker 等等...均是Android 前輩們夜以繼日的成果。而現(xiàn)在熱修復(fù)被廣泛地應(yīng)用于Android 應(yīng)用和游戲,運用并理解熱修復(fù)框架在面試中也是加分項。所以,趕緊學起來吧...
本文以Tinker 作為學習對象,主要講述各開源框架的對比和記錄Tinker 的Demo 集成過程。
熱修復(fù)框架原理總結(jié)
這一節(jié)篇幅較長,主要是用自己的話來總結(jié)各熱修復(fù)框架的實現(xiàn)原理。如果想看Tinker接入實現(xiàn)的同學可進入下一章節(jié)。Android 熱修復(fù) - Tinker 實現(xiàn)及踩過的坑
Nuwa 實現(xiàn)原理:
最早看到熱修復(fù)框架的相關(guān)文章就是Qzone官方的文章,但是Qzone熱修復(fù)技術(shù)的實現(xiàn)代碼并沒有開源。不過GitHub上有一開源的熱修復(fù)框架Nuwa,實現(xiàn)原理和其相似。這里我們以Qzone為例進行分析。
Qzone的實現(xiàn)原理是生成差分dex文件,將patch.dex插到dexElements的最前面。但patch.dex中的類patchA.java會引用classes.dex中的類classesB.java,如果這兩個類所在的patch.dex和classes.dex不是同一個文件就會報錯。
疑惑的Qzone技術(shù)大佬發(fā)現(xiàn)classes.dex和classes2.dex也不是同一個文件,為啥不報錯?于是繼續(xù)查,發(fā)現(xiàn)了這個判斷
if(!fromUnverifiedConstant && IS_CLASS_FLAG_SET(referrer, CLASS_ISPREVERIFIED)){
如果被引用者(也就是classesB.java)這個類被打上了CLASS_ISPREVERIFIED標志,那么就會進行dex的校驗。校驗不過就報錯了。
那么這個標志是什么時候被打上去的?
在apk安裝的時候,虛擬機會將dex優(yōu)化成odex后才拿去執(zhí)行。在這個過程中會對所有class進行校驗。
怎么校驗的?
假設(shè)classesB.java類在它的static方法,private方法,構(gòu)造函數(shù),override方法中直接引用到classesC.java類。如果classesB.java類和classesC.java類在同一個dex中,那么classesB.java類就會被打上CLASS_ISPREVERIFIED標記,被打上這個標記的類不能被其他dex中的類引用,否則就會報錯。所以要防止類被打上CLASS_ISPREVERIFIED的標志。
如何防止類被打上CLASS_ISPREVERIFIED的標志?
Common類會被打包成單獨的hack.dex,這樣當安裝apk的時候,classes.dex內(nèi)的類都會引用一個在不相同dex中的Common類,這樣就防止了類被打上CLASS_ISPREVERIFIED的標志了,只要沒被打上這個標志的類都可以進行打補丁操作。
優(yōu)點:
開發(fā)透明,簡單;
熱修復(fù)成功率高。
缺點:
在Art 上表現(xiàn)為補丁包較大;
在Dalvik 上性能消耗較大。
Robust實現(xiàn)原理:
Robust 插件對每個產(chǎn)品代碼的每個函數(shù)都在編譯打包階段自動的插入了一段代碼。通過判斷 if(changeQuickRedirect != null) 來確定是否進行熱修復(fù),當 changeQuickRedirect 不為 null 時,調(diào)用 patch.dex 中同名類的同名方法達到 hotfix 的目的。
如何調(diào)用呢?
生成的patch.dex 中有兩個主要類,PatchesInfoImpl.java 和修復(fù)后的同名類 APatch.java??蛻舳四玫絧atch.dex 后,用DexClassLoader 加載patch.dex,反射拿到PatchesInfoImpl.java 這個 class。并創(chuàng)建這個class 的一個對象。然后通過這個對象知道被替換的是誰,給它的變量changeQuickRedirect 賦值為 patch.dex 中的 APatch 的對象,這樣就會去執(zhí)行補丁包中的方法了。
大致流程圖如下所示:A_old 表示未被修復(fù)的原有類,A_new 表示已修復(fù)的新類。
Robust 原理流程圖
優(yōu)點
兼容性高,開發(fā)透明;
實時生效。
缺點
會增大方法數(shù),影響運行效率;
暫不支持 so 文件和資源的替換。
Andfix 實現(xiàn)原理:
Andfix 采用的方法是,在已經(jīng)加載了的類中直接在 native 層替換掉原有方法,是在原來類的基礎(chǔ)上進行修改的。其核心在于 replaceMethod 函數(shù),所以只支持方法替換,對于方法的增刪,資源更新,so 文件更新及類和屬性的替換等都是不支持的。
Andfix 的實現(xiàn)偏 native 層,筆者能力有限,其具體實現(xiàn)過程,就不妄加總結(jié)了。
更多實現(xiàn)細節(jié)請看 Andfix 官網(wǎng)文章
優(yōu)點
立即生效,消耗低;
補丁包較小。
缺點
僅支持方法替換;
兼容性不佳,對部分機型暫不支持。
Tinker 實現(xiàn)原理:
在 App 運行到一半的時候,所有需要發(fā)生變更的 Class 已經(jīng)被加載過了,在Android 上是無法對一個 Class 進行卸載的。而 Tinker 的方案,都是讓 Classloader 去加載新的類。如果不重啟,原來的類還在虛擬機中,就無法加載新類。因此,只有在下次重啟的時候,在還沒走到業(yè)務(wù)邏輯之前搶先加載補丁中的新類,這樣后續(xù)訪問這個類時,就會 Resolve 為新的類。從而達到熱修復(fù)的目的。
Tinker 的實現(xiàn)過程更像是在 Qzone 熱修復(fù)方案上做優(yōu)化。核心點是性能最優(yōu),消耗最低。
經(jīng) Tinker 開發(fā)人員調(diào)研,Qzone 的方案最大挑戰(zhàn)在于性能,即Dalvik平臺存在插樁導(dǎo)致的性能損耗,Art平臺由于地址偏移問題導(dǎo)致補丁包可能過大的問題。為了避免這兩個問題,根據(jù) Instant Run 的全量替換新的 Dex 的思路,于是決定將新舊兩個Dex 的差異放到補丁包中。
經(jīng)過調(diào)研,BsDiff 算法對 Dex 支持效果不太好,所以,Tinker 開發(fā)團隊人員自研了 DexDiff 算法。
最終, BsDiff 加載 so 和部分資源文件,DexDiff 加載 Dex文件,以達到性能最優(yōu)。但是這個方案也有缺點,就是占用 ROM 較大。好吧!現(xiàn)在手機內(nèi)存都不小,多幾十 M 可以接受。
優(yōu)點
補丁包較小,消耗較小;
開發(fā)透明,文檔豐富。
缺點
占用 ROM 較大;
需要重啟才能生效。
數(shù)據(jù)對比:
Type
Nuwa
Robust
Andfix
Tinker
Company
Null
Meituan
Alibaba
Tencent
開發(fā)時間
2015
2016
2015
2016
替換類
√
X
X
√
替換So
X
X
X
√
替換資源
√
X
X
√
即時生效
X
√
√
X
成功率
較高
最高
一般
較高
接口文檔
★★
★★
★★
★★★★
寫在后頭
單就熱修復(fù)線上 APP 某一處或多處 bug 來說,Andfix能做到即時修復(fù),且操作簡單,不用生成較多的 patch.dex 包,能輕松解決緊急問題。
但對于如非緊急 bug 的修復(fù)及小版本的發(fā)布,對即時生效性要求不高的情況,Tinker 支持的替換內(nèi)容較豐富,更勝一籌。
阿里將 Andfix 升級為商業(yè)版 SDK Sophix;騰訊將 Tinker 升級為 Bugly。
Sophix 不但支持即時修復(fù),還支持再次啟動修復(fù)類、so 文件、資源等。作為商用 APP 集成 Sophix 是很好的選擇。
但 Tinker 的開源,為其帶來了大量的使用者和測試者,除此以外還與各大手機廠商建立聯(lián)系,使得各廠商在系統(tǒng)定制時也會考慮是否影響熱修復(fù)的問題。所以 Tinker 的兼容性可見一斑。
總的來說,各有千秋,各需所需吧。
我們這里以 Tinker 為學習對象,接下來先讓 Tinker-Demo 跑起來,看一下實際效果。
Android 熱修復(fù) - Tinker 實現(xiàn)及踩過的坑
總結(jié)
以上是生活随笔為你收集整理的android热修复原理底层替换,Android 热修复 - 各框架原理学习及对比的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 加载条封装,Androi
- 下一篇: android q测试机型,小米9安卓Q