熱補(bǔ)丁動(dòng)態(tài)修復(fù)技術(shù)調(diào)研

一谣妻、背景:

如果發(fā)布了一個(gè)release包,但是里面出現(xiàn)了嚴(yán)重的事故級(jí)別(某些等不及下一版本迭代就得修復(fù))的bug卒稳,那么站在公司角度蹋半,這邊QA,開發(fā)充坑,客服减江,甚至PR等部門都得加班趕忙發(fā)包重現(xiàn)覆蓋染突,耗費(fèi)的資源代價(jià)相當(dāng)?shù)拇螅鰡栴}的或許只是一兩行代碼辈灼;站在用戶User角度份企,剛剛下載了一個(gè)包,準(zhǔn)備嘗鮮巡莹,發(fā)現(xiàn)又讓更新司志,是不是很煩,如果新包打開就崩潰了降宅,很多就會(huì)去市場評(píng)論骂远,“垃圾,更新之后閃退”云云腰根,抑或“垃圾激才,天天要更新”。
在這個(gè)基礎(chǔ)上熱更新技術(shù)出現(xiàn)了额嘿,即使發(fā)出了release包瘸恼,如果出現(xiàn)某些等不及下一版本迭代就得修復(fù)的bug,向用戶下發(fā)Patch册养,在用戶無感知的情況下东帅,修復(fù)了bug或問題。

二捕儒、類型:

花了幾天查閱一些資料冰啃,去了解一些目前的熱更新方案邓夕,主要有以下兩大類型:

1刘莹、【基于native hook方案】

參考文章:理解 Android Hook 技術(shù)以及簡單實(shí)戰(zhàn)

  • Dexposed(from 淘寶)

  • AndFix (from 支付寶)

無需重啟Application、無需啟動(dòng)Activity即可更新Java方法 安卓代碼要達(dá)到真正“熱”更新的效果焚刚,也只有基于AOP這種技術(shù)点弯,就是在方法級(jí)別這個(gè)粒度做替換。

2矿咕、【基于multidex的熱更新框架】

  • ClassLoader(originally from qq空間團(tuán)隊(duì) --原始)

    在它之后和他有相同原理的其他熱門開源庫有:
    • Nuwa
    • HotFix
    • DroidFix
    • Tinker(來自微信)

需要重啟Activity或重啟Application達(dá)到更新效果抢肛。

3、【基于Instant Run原理】

  • Robust

前兩個(gè)都會(huì)存在一些兼容性問題碳柱,為此美團(tuán)借鑒了Instant Run原理捡絮,推出Android熱更新方案Robust

三、對(duì)比

  • 基于native hook的方案:需要針對(duì)dalvik虛擬機(jī)和art虛擬機(jī)做適配莲镣,需要考慮指令集的兼容問題福稳,需要native代碼支持,兼容性上會(huì)有一定的影響瑞侮;但是無需重啟Application的圆、無需啟動(dòng)Activity即可更新Java方法鼓拧。
  • 基于Multidex的方案,需要反射更改DexElements越妈,改變Dex的加載順序季俩,這使得patch需要在下次啟動(dòng)時(shí)才能生效,實(shí)時(shí)性就受到了影響梅掠,同時(shí)這種方案在android N [speed-profile]編譯模式下可能會(huì)有問題酌住,可以參考Android N混合編譯與對(duì)熱補(bǔ)丁影響解析
  • 各大熱補(bǔ)丁方案分析和比較

四、具體原理

【Dexposed】

基于exposed的AOP框架瓤檐,方法級(jí)粒度赂韵,可以進(jìn)行AOP編程、插樁挠蛉、熱補(bǔ)丁祭示、SDK hook等功能。是真正程度上的熱更新谴古。無需重啟Application质涛、無需啟動(dòng)Activity即可更新Java方法£#基于AOP這種技術(shù)汇陆,就是在方法級(jí)別這個(gè)粒度做替換。

我們知道带饱,應(yīng)用啟動(dòng)的時(shí)候毡代,都會(huì)fork zygote進(jìn)程,裝載class和invoke各種初始化方法勺疼,Xposed就是在這個(gè)過程中教寂,替換了app_process,hook了各種入口級(jí)方法(比如handleBindApplication执庐、ServerThread酪耕、ActivityThread、ApplicationPackageManager的getResourcesForApplication等)轨淌,加載XposedBridge.jar提供動(dòng)態(tài)hook基礎(chǔ)迂烁。方法級(jí)的替換是指,可以在方法前递鹉、方法后插入代碼盟步,或者直接替換方法。只能針對(duì)java方法做攔截躏结,不支持C的方法却盘。

缺點(diǎn):

1.不支持AndroidRuntime(5.0+)
2.如果線上release版本進(jìn)行了混淆,那寫補(bǔ)丁也是一件很痛苦的事情,需要反射寫混淆后的代碼谷炸,粒度太細(xì)北专,要替換的方法多的話,工作量會(huì)比較大旬陡。反射+內(nèi)部類拓颓,可能還有包名和內(nèi)部類的名字沖突,總而言之就是寫得很痛苦描孟。

【AndFix】

同樣是方法的hook驶睦,AndFix不像Dexposed從Method入手,而是以Field為切入點(diǎn)匿醒。

【ClassLoader】

其他相同原理開源庫鏈接:Nuwa场航, HotFixDroidFix廉羔,Tinker溉痢。
Classloader的原理就和上面兩個(gè)不一樣了,參考文章安卓App熱補(bǔ)丁動(dòng)態(tài)修復(fù)技術(shù)介紹憋他,以及Android dex分包方案孩饼,所以這倆篇?jiǎng)?wù)必要看。這里就不對(duì)三個(gè)框架做過多對(duì)比了竹挡,因?yàn)樵矶家恢露迫ⅲ瑢?shí)現(xiàn)的代碼可能差異并不是特別大。
總結(jié)一下就是:
  1. 一個(gè)ClassLoader可以包含多個(gè)dex文件揪罕,每個(gè)dex文件是一個(gè)Element梯码,多個(gè)dex文件排列成一個(gè)有序的數(shù)組dexElements,當(dāng)找類的時(shí)候好啰,會(huì)按順序遍歷dex文件轩娶,然后從當(dāng)前遍歷的dex文件中找類,如果找類則返回坎怪,如果找不到從下一個(gè)dex文件繼續(xù)查找罢坝。

  2. 把多個(gè)dex放進(jìn)app的classloader之中廓握,從而使得所有dex的類都能被找到搅窿。而實(shí)際上findClass的過程中,如果出現(xiàn)了重復(fù)的類隙券,改變類加載的實(shí)現(xiàn)男应,是會(huì)使用第一個(gè)找到的類的。

  3. 如果在不同的dex中有相同的類存在娱仔,那么會(huì)優(yōu)先選擇排在前面的dex文件的類沐飘。所以我們可以把有問題的類打包到一個(gè)dex(patch.dex)中去,然后把這個(gè)dex插入到Elements的最前面。

  4. 只要把有問題的類修復(fù)后耐朴,放到一個(gè)單獨(dú)的dex借卧,通過反射插入到dexElements數(shù)組的最前面,就可以讓虛擬機(jī)加載到打完補(bǔ)丁的class了筛峭。

  5. 但在實(shí)踐中铐刘,會(huì)發(fā)現(xiàn)運(yùn)行加載類的時(shí)候報(bào)preverified錯(cuò)誤,原來在DexPrepare.cpp影晓,將dex轉(zhuǎn)化成odex的過程中镰吵,會(huì)在DexVerify.cpp進(jìn)行校驗(yàn),驗(yàn)證如果直接引用到的類和clazz是否在同一個(gè)dex挂签,如果是疤祭,則會(huì)打上CLASS_ISPREVERIFIED標(biāo)志。通過在所有類(Application除外饵婆,當(dāng)時(shí)還沒加載自定義類的代碼)的構(gòu)造函數(shù)插入一個(gè)對(duì)在單獨(dú)的dex的類的引用勺馆,就可以解決這個(gè)問題∏群耍空間使用了javaassist進(jìn)行編譯時(shí)字節(jié)碼插入谓传。總結(jié)起來就是兩點(diǎn)芹关,第一是動(dòng)態(tài)改變BaseDexClassLoader對(duì)象間接引用的dexElements续挟,第二是在app打包的時(shí)候,阻止相關(guān)類去打上CLASS_ISPREVERIFIED標(biāo)志侥衬。

關(guān)于這種方式想了解更多的可以參考文章:HongYang大神--Android 熱補(bǔ)丁動(dòng)態(tài)修復(fù)框架小結(jié)

【Robust】

Robust開源GitHub
Android熱更新方案之美團(tuán)Robust

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诗祸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子轴总,更是在濱河造成了極大的恐慌直颅,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怀樟,死亡現(xiàn)場離奇詭異功偿,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)往堡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門械荷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人虑灰,你說我怎么就攤上這事吨瞎。” “怎么了穆咐?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵颤诀,是天一觀的道長字旭。 經(jīng)常有香客問我,道長崖叫,這世上最難降的妖魔是什么遗淳? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮心傀,結(jié)果婚禮上洲脂,老公的妹妹穿的比我還像新娘。我一直安慰自己剧包,他們只是感情好恐锦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著疆液,像睡著了一般一铅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上堕油,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天潘飘,我揣著相機(jī)與錄音,去河邊找鬼掉缺。 笑死卜录,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的眶明。 我是一名探鬼主播艰毒,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼搜囱!你這毒婦竟也來了丑瞧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤蜀肘,失蹤者是張志新(化名)和其女友劉穎绊汹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扮宠,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡西乖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坛增。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片获雕。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖轿偎,靈堂內(nèi)的尸體忽然破棺而出典鸡,到底是詐尸還是另有隱情被廓,我是刑警寧澤坏晦,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響昆婿,放射性物質(zhì)發(fā)生泄漏球碉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一仓蛆、第九天 我趴在偏房一處隱蔽的房頂上張望睁冬。 院中可真熱鬧,春花似錦看疙、人聲如沸豆拨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽施禾。三九已至,卻和暖如春搁胆,著一層夾襖步出監(jiān)牢的瞬間弥搞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工渠旁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留攀例,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓顾腊,卻偏偏與公主長得像粤铭,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杂靶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容