Android熱修復(fù)技術(shù)選型

目前Android業(yè)內(nèi)刀闷,熱修復(fù)技術(shù)百花齊放,各大廠都推出了自己的熱修復(fù)方案嘿架,使用的技術(shù)方案也各有所異,當(dāng)然各個方案也都存在各自的局限性啸箫。在面對眾多的方案耸彪,希望通過梳理這些熱修復(fù)方案的對比及實現(xiàn)原理,掌握熱修復(fù)技術(shù)的本質(zhì)忘苛,同時也對項目接入做好準(zhǔn)備蝉娜。

什么是熱修復(fù)技術(shù)?

簡單來說扎唾,就是通過下發(fā)補(bǔ)丁包召川,讓已安裝的客戶端動態(tài)更新,讓用戶可以不用重新安裝APP胸遇,就能夠修復(fù)軟件缺陷的一種技術(shù)荧呐。

隨著熱修復(fù)技術(shù)的發(fā)展,不僅可以修復(fù)代碼,同時可以修復(fù)資源文件及SO庫倍阐。

怎么選擇熱修復(fù)技術(shù)方案概疆?

國內(nèi)主流的技術(shù)方案

缺點

接入復(fù)雜

目前最快捷的集成方式是 集成 bugly 升級sdk。

需要的工作

代理 Application

接入 tinker-support 插件

編寫tinker gradle 腳本

打包復(fù)雜

每次打包需要修改tinker gradle 腳本的配置

補(bǔ)丁激活成功率低

測試下來發(fā)現(xiàn)激活成功率 大概 60%

補(bǔ)丁合成dex性能消耗大

主流配置的機(jī)器峰搪,平均合成時間 1800秒

價格

基礎(chǔ)版 免費(fèi):最大補(bǔ)丁大小:500k 日請求量 <1萬

專業(yè)版 399 - 2899元/月

Sophix

優(yōu)點

補(bǔ)丁即時生效岔冀,不需要應(yīng)用重啟;

補(bǔ)丁包同樣采用差量技術(shù)概耻,生成的PATCH體積惺固住;

對應(yīng)用無侵入鞠柄,幾乎無性能損耗侦高;

兩行代碼,傻瓜式接入厌杜。

價格

免費(fèi)閾值:月活設(shè)備(MAU): 5萬矫膨。

每個月,每臺設(shè)備收費(fèi)0.015元期奔。

計費(fèi)周期:系統(tǒng)每日生成賬單,進(jìn)行結(jié)算危尿。當(dāng)月收取過的呐萌,不再進(jìn)行收費(fèi)。即只計算日增量設(shè)備

Robust

java hook 插樁

優(yōu)點

無差別兼容Android2.3-8.0版本谊娇;

無需重啟補(bǔ)丁實時生效肺孤,

補(bǔ)丁修補(bǔ)成功率高達(dá)99.9%(所有熱修復(fù)方案中成功率最高的)

缺點

只支持方法級別的Bug修復(fù),不支持資源及so

bug修復(fù)通過java hook 代碼實現(xiàn)

補(bǔ)丁的下發(fā)和合并等需要自己實現(xiàn)

總結(jié)



如果考慮付費(fèi)济欢,推薦選擇阿里的Sophix赠堵,Sophix是綜合優(yōu)化的產(chǎn)物,功能完善法褥、開發(fā)簡單透明茫叭、提供分發(fā)及監(jiān)控管理。

如果不考慮付費(fèi)半等,只需支持方法級別的Bug修復(fù)揍愁,不支持資源及so,推薦使用Robust杀饵。補(bǔ)丁修補(bǔ)成功率高達(dá)99.9%(所有熱修復(fù)方案中成功率最高的)

如果考慮需要同時支持資源及so莽囤,使用Tinker。不建議使用切距,因為實現(xiàn)原理是 dex合成后替換朽缎,dex合成成功率不高(60%)

如果公司綜合實力強(qiáng),可考慮自研,靈活性及可控制最強(qiáng)话肖。

從Github上的熱度及提交記錄上看北秽,nuwa、AndFix狼牺、Amigo等的提交都是2 years ago羡儿。

內(nèi)業(yè)主要熱修復(fù)技術(shù)方案原理

代碼熱修復(fù)方案的兩個方向

底層替換和類加載(dex插入/替換)

類加載有兩種實現(xiàn):dexElements和替換dex;所以又稱三大流派

美團(tuán) Robust 這種 java方法插樁hook的是钥,只能實現(xiàn)代碼修復(fù)掠归,無法實現(xiàn)資源和so修復(fù);所以不在常規(guī)討論范圍內(nèi)悄泥。

底層替換方案

代表:阿里系的 Andfix HotFix

原理

通過Andfix提供的工具對比出新舊apk 的?classes.dex?文件的差異虏冻,并生成patch壓縮包(jar包)

壓縮包中比較關(guān)鍵的是?PATCH.MF?(補(bǔ)丁類名)和?diff.dex?(補(bǔ)丁方法)

虛擬機(jī)通過 jar包 讀取 補(bǔ)丁類名和補(bǔ)丁方法

通過classLoader,找到要修復(fù)的bug類名及方法

利用hook技術(shù)弹囚,在native修改指ArtMethod針變量厨相,使其指向補(bǔ)丁方法,從而完成bug修復(fù)鸥鹉。

優(yōu)點

在類加載后蛮穿,動態(tài)修改native指針,修復(fù)即時生效毁渗,無需冷啟動

缺點

類已經(jīng)被加載践磅,內(nèi)存中方法描述符(結(jié)構(gòu)體)已經(jīng)固定,所以只能替換灸异,不能做新增修復(fù)府适。

在Native操作指針時,強(qiáng)轉(zhuǎn)ArtMethod的類型是AndFix寫死的肺樟,無法保證是運(yùn)行時的ArtMethod結(jié)構(gòu)檐春,這會產(chǎn)生十分嚴(yán)重的兼容問題

實踐發(fā)現(xiàn)Andfix?修復(fù)成功率非常低?,時常出現(xiàn)崩潰么伯,補(bǔ)丁無效的現(xiàn)象

類加載方案

代表:騰訊系的 Qzone超級補(bǔ)丁(dex插入) Tinker(dex替換)

dex插入

增量Dex

原理

Hook ClassLoader.pathList.dexElements[]

將補(bǔ)丁的dex插入到數(shù)組的最前端疟暖。

ClassLoader的findClass是通過遍歷dexElements[]中的dex來尋找類的。所以會優(yōu)先查找到修復(fù)的類田柔。從而達(dá)到修復(fù)的效果誓篱。

VM規(guī)則判斷

Vm的判定規(guī)則:“當(dāng)一個類中引用了另外一個類,則一般要求兩個類來自同一個Dex文件”凯楔。

CLASS_ISPREVERIFIED?是觸發(fā)Vm判定規(guī)則的前提窜骄。

增量方案為解決這個問題,需要進(jìn)行“打樁”摆屯。

打樁的目的就是防止類被打上?CLASS_ISPREVERIFIED?標(biāo)簽邻遏。

打樁糠亩,就是在所有類中分別引用另外一個獨(dú)立Dex文件(為了打樁特意封裝的)中的類。通常做法是在每一個類中增加構(gòu)造器并引用另外一個dex中的類准验。

在類加載的最后階段赎线,虛擬機(jī)會對未打上?CLASS_ISPREVERIFIED?標(biāo)簽的類 再次進(jìn)行?校驗和優(yōu)化?,如果在同一時間點加載大量類糊饱,那么就會出現(xiàn)嚴(yán)重的性能問題垂寥,如啟動時白屏。

優(yōu)點

不需要考慮對dalvik虛擬機(jī)和art虛擬機(jī)做適配

代碼是非侵入式的另锋,對apk體積影響不大

缺點

需要下次啟動才修復(fù)

性能損耗大滞项,為了避免類被加上?CLASS_ISPREVERIFIED,使用插樁夭坪,單獨(dú)放一個幫助類在獨(dú)立的dex中讓其他類調(diào)用文判。可能導(dǎo)致嚴(yán)重的性能問題室梅,如啟動時白屏戏仓。

dex替換

全量Dex替換

原理

為了避免dex插樁帶來的性能損耗,dex替換采取另外的方式(整體替換dex)亡鼠。

提供dex差量包(只包含patch代碼的dex)

將patch.dex與應(yīng)用的classes.dex合并成一個完整的dex

加載完整dex得到dexFile對象作為參數(shù)構(gòu)建一個Element對象

整體替換掉舊的dex-Elements數(shù)組

優(yōu)點

相比 dex插入赏殃,dex替換的優(yōu)點

減少了dex插樁帶來的性能損耗

缺點

Dex合并內(nèi)存消耗在虛擬機(jī)堆內(nèi)存(vm heap)上,容易OOM间涵,最后導(dǎo)致合并失敗

兩種方案總結(jié)

底層替換存在不同定制Rom的兼容性問題仁热,同時不能做新增field的修復(fù),但修復(fù)立即生效浑厚。

類加載方案在合成全量補(bǔ)丁的時候存在性能問題,修復(fù)需要重啟應(yīng)用(冷啟動)根盒,但是兼容性較好钳幅。

Sophix 代碼熱修復(fù)-雙劍合璧

Sophix對類文件修復(fù) 采用底層替換方案為主,類加載方案為次(兜底策略)的模式炎滞,將二者結(jié)合起來敢艰,并對二者另辟蹊徑,加以突破册赛。

基于底層替換方案的突破

底層替換方案通過在運(yùn)行時利用hook操作native指針實現(xiàn)“熱”的特性钠导。但這里有一個關(guān)鍵點,底層替換所操作的指針森瘪,實際上是?ArtMethod?牡属。

在類被加載,類中的每個方法都會有對應(yīng)的ArtMethod扼睬,它記錄了方法包括所屬類和內(nèi)存地址信息

Andfix正是通過篡改ArtMethod逮栅,將補(bǔ)丁方法ArtMethod的成員值逐一賦給舊方法,實現(xiàn)替換。

問題就出現(xiàn)在?逐一替換?上措伐。因為Andfix的?ArtMethod?方法結(jié)構(gòu)是根據(jù)Android開源代碼寫死的特纤,面對國內(nèi)廠商的定制,經(jīng)常會導(dǎo)致兩者ArtMethod方法結(jié)構(gòu)不一致侥加,這也是兼容問題產(chǎn)生的根本原因捧存。

為了解決這個問題,Sophix采用了對舊ArtMethod進(jìn)行?完整替換担败。

通過動態(tài)測量ArtMethod的size(通過c層的mempy(dest ,src ,size)方法)昔穴,進(jìn)行全量拷貝。這樣做無論ArtMethod被修改成什么樣氢架,只需要統(tǒng)一執(zhí)行拷貝傻咖,就可以完成替換,完全無視修改虛擬機(jī)導(dǎo)致的ArtMethod結(jié)構(gòu)差異岖研。

另辟蹊徑的冷啟動修復(fù)

底層替換雖能使修復(fù)即時生效卿操,但由于類加載后,方法結(jié)構(gòu)已固定孙援,這就造成使用上會有諸多限制害淤。

相反類加載方案的使用場景更為廣泛。

Sophix使用類加載作為兜底方案拓售。在熱部署無法使用的情況下窥摄,自動降級為冷部署方案。

無論是冷部署還是熱部署础淤,都需要通過同一套補(bǔ)丁兼顧崭放。

Art虛擬機(jī)

在Art虛擬機(jī)下,默認(rèn)支持多dex加載鸽凶,虛擬機(jī)會優(yōu)先加載命名為classes.dex的文件币砂。

Sophix利用了這一點,將補(bǔ)丁文件命名為classes.dex玻侥,并對原有dex文件進(jìn)行排序决摧。這樣一來,art虛擬機(jī)就會先加載補(bǔ)丁文件凑兰,后續(xù)加載的同類名的類會被忽略掌桩,最后將加載得到的dexFile把dexElements整體替換。

Dalvik虛擬機(jī)

Dalvik默認(rèn)只加載classes.dex姑食,其他dex則被忽略波岛。

Sophix就需要一個全量dex。

tinker采用自主研發(fā)的dexDiff技術(shù)音半,從方法和指令的維度進(jìn)行dex合成盆色,但Dex合成過程發(fā)生在虛擬機(jī)堆內(nèi)存上灰蛙,修復(fù)的成功率極大的受到性能問題的影響。

為了解決這個問題隔躲,Sophix換了一種思路摩梧,從類的維度,對照補(bǔ)丁包中出現(xiàn)的類宣旱,在原有包中做刪除操作仅父。為了避免刪除整個類信息而導(dǎo)致dex結(jié)構(gòu)發(fā)生偏移,所以只對舊包中類的入口進(jìn)行刪除浑吟,實際上類的信息還在dex包中笙纤。這樣一來嘱朽,冷啟動后锣杂,原有的類就不會被加載叙身,相比Tinker的合成方案及汉,Sophix的思路更為輕量化

總結(jié)

至此膘螟,Sophix對類文件修復(fù)的基本原理描述完畢虽惭。

可以說Sophix吸取了百家之長敌蚜,對問題的解決之法堪稱巧妙候衍,展現(xiàn)出底層技術(shù)的重要性笼蛛,若沒有對虛擬機(jī)等底層技術(shù)的深耕探索,在系統(tǒng)框架的紛繁規(guī)則面前蛉鹿,也只能至于庭前止步滨砍。

參考&擴(kuò)展

Android熱修復(fù)技術(shù),你會怎么選妖异?

兩種熱修復(fù)方案及Sophix原理

Android熱修復(fù)技術(shù)選型——三大流派解析

為什么使用 Tinker惋戏?

Sophix產(chǎn)品優(yōu)勢

Tinker 價格

Sophix 價格

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市他膳,隨后出現(xiàn)的幾起案子响逢,更是在濱河造成了極大的恐慌,老刑警劉巖矩乐,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄句,死亡現(xiàn)場離奇詭異回论,居然都是意外死亡散罕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門傀蓉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來欧漱,“玉大人,你說我怎么就攤上這事葬燎∥笊酰” “怎么了缚甩?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長窑邦。 經(jīng)常有香客問我擅威,道長,這世上最難降的妖魔是什么冈钦? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任郊丛,我火速辦了婚禮,結(jié)果婚禮上瞧筛,老公的妹妹穿的比我還像新娘厉熟。我一直安慰自己,他們只是感情好较幌,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布揍瑟。 她就那樣靜靜地躺著,像睡著了一般乍炉。 火紅的嫁衣襯著肌膚如雪绢片。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天恩急,我揣著相機(jī)與錄音杉畜,去河邊找鬼。 笑死衷恭,一個胖子當(dāng)著我的面吹牛此叠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播随珠,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼灭袁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了窗看?” 一聲冷哼從身側(cè)響起茸歧,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎显沈,沒想到半個月后软瞎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拉讯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年涤浇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片魔慷。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡只锭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出院尔,到底是詐尸還是另有隱情蜻展,我是刑警寧澤喉誊,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站纵顾,受9級特大地震影響伍茄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜施逾,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一幻林、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧音念,春花似錦沪饺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至讥脐,卻和暖如春遭居,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旬渠。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工俱萍, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人告丢。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓枪蘑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親岖免。 傳聞我的和親對象是個殘疾皇子岳颇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355