真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

安卓App熱補(bǔ)丁動(dòng)態(tài)修復(fù)技術(shù)是什么

這篇文章將為大家詳細(xì)講解有關(guān)安卓App熱補(bǔ)丁動(dòng)態(tài)修復(fù)技術(shù)是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

創(chuàng)新互聯(lián)公司主營金鄉(xiāng)網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,App定制開發(fā),金鄉(xiāng)h5微信小程序定制開發(fā)搭建,金鄉(xiāng)網(wǎng)站營銷推廣歡迎金鄉(xiāng)等地區(qū)企業(yè)咨詢

1.背景

當(dāng)一個(gè)App發(fā)布之后,突然發(fā)現(xiàn)了一個(gè)嚴(yán)重bug需要進(jìn)行緊急修復(fù),這時(shí)候公司各方就會忙得焦頭爛額:重新打包App、測試、向各個(gè)應(yīng)用市場和渠道換包、提示用戶升級、用戶下載、覆蓋安裝。有時(shí)候僅僅是為了修改了一行代碼,也要付出巨大的成本進(jìn)行換包和重新發(fā)布。
這時(shí)候就提出一個(gè)問題:有沒有辦法以補(bǔ)丁的方式動(dòng)態(tài)修復(fù)緊急Bug,不再需要重新發(fā)布App,不再需要用戶重新下載,覆蓋安裝?
雖然Android系統(tǒng)并沒有提供這個(gè)技術(shù),但是很幸運(yùn)的告訴大家,答案是:可以,我們QQ空間提出了熱補(bǔ)丁動(dòng)態(tài)修復(fù)技術(shù)來解決以上這些問題。

2.實(shí)際案例

空間Android獨(dú)立版5.2發(fā)布后,收到用戶反饋,結(jié)合版無法跳轉(zhuǎn)到獨(dú)立版的訪客界面,每天都較大的反饋。在以前只能緊急換包,重新發(fā)布。成本非常高,也影響用戶的口碑。最終決定使用熱補(bǔ)丁動(dòng)態(tài)修復(fù)技術(shù),向用戶下發(fā)Patch,在用戶無感知的情況下,修復(fù)了外網(wǎng)問題,取得非常好的效果。

3.解決方案

該方案基于的是android dex分包方案的,關(guān)于dex分包方案,網(wǎng)上有幾篇解釋了,所以這里就不再贅述,具體可以看這里
簡單的概括一下,就是把多個(gè)dex文件塞入到app的classloader之中,但是android dex拆包方案中的類是沒有重復(fù)的,如果classes.dex和classes1.dex中有重復(fù)的類,當(dāng)用到這個(gè)重復(fù)的類的時(shí)候,系統(tǒng)會選擇哪個(gè)類進(jìn)行加載呢?
讓我們來看看類加載的代碼:

一個(gè)ClassLoader可以包含多個(gè)dex文件,每個(gè)dex文件是一個(gè)Element,多個(gè)dex文件排列成一個(gè)有序的數(shù)組dexElements,當(dāng)找類的時(shí)候,會按順序遍歷dex文件,然后從當(dāng)前遍歷的dex文件中找類,如果找類則返回,如果找不到從下一個(gè)dex文件繼續(xù)查找。
理論上,如果在不同的dex中有相同的類存在,那么會優(yōu)先選擇排在前面的dex文件的類,如下圖:

在此基礎(chǔ)上,我們構(gòu)想了熱補(bǔ)丁的方案,把有問題的類打包到一個(gè)dex(patch.dex)中去,然后把這個(gè)dex插入到Elements的最前面,如下圖:

好,該方案基于第二個(gè)拆分dex的方案,方案實(shí)現(xiàn)如果懂拆分dex的原理的話,大家應(yīng)該很快就會實(shí)現(xiàn)該方案,如果沒有拆分dex的項(xiàng)目的話,可以參考一下谷歌的multidex方案實(shí)現(xiàn)。然后在插入數(shù)組的時(shí)候,把補(bǔ)丁包插入到最前面去。
好,看似問題很簡單,輕松的搞定了,讓我們來試驗(yàn)一下,修改某個(gè)類,然后打包成dex,插入到classloader,當(dāng)加載類的時(shí)候出現(xiàn)了(本例中是QzoneActivityManager要被替換):

為什么會出現(xiàn)以上問題呢?
從log的意思上來講,ModuleManager引用了QzoneActivityManager,但是發(fā)現(xiàn)這這兩個(gè)類所在的dex不在一起,其中:

  1. ModuleManager在classes.dex中

  2. QzoneActivityManager在patch.dex中
    結(jié)果發(fā)生了錯(cuò)誤。
    這里有個(gè)問題,拆分dex的很多類都不是在同一個(gè)dex內(nèi)的,怎么沒有問題?

讓我們搜索一下拋出錯(cuò)誤的代碼所在,嘿咻嘿咻,找到了一下代碼:

從代碼上來看,如果兩個(gè)相關(guān)聯(lián)的類在不同的dex中就會報(bào)錯(cuò),但是拆分dex沒有報(bào)錯(cuò)這是為什么,原來這個(gè)校驗(yàn)的前提是:

如果引用者(也就是ModuleManager)這個(gè)類被打上了CLASS_ISPREVERIFIED標(biāo)志,那么就會進(jìn)行dex的校驗(yàn)。那么這個(gè)標(biāo)志是什么時(shí)候被打上去的?讓我們在繼續(xù)搜索一下代碼,嘿咻嘿咻~,在DexPrepare.cpp找到了一下代碼:

這段代碼是dex轉(zhuǎn)化成odex(dexopt)的代碼中的一段,我們知道當(dāng)一個(gè)apk在安裝的時(shí)候,apk中的classes.dex會被虛擬機(jī)(dexopt)優(yōu)化成odex文件,然后才會拿去執(zhí)行。
虛擬機(jī)在啟動(dòng)的時(shí)候,會有許多的啟動(dòng)參數(shù),其中一項(xiàng)就是verify選項(xiàng),當(dāng)verify選項(xiàng)被打開的時(shí)候,上面doVerify變量為true,那么就會執(zhí)行dvmVerifyClass進(jìn)行類的校驗(yàn),如果dvmVerifyClass校驗(yàn)類成功,那么這個(gè)類會被打上CLASS_ISPREVERIFIED的標(biāo)志,那么具體的校驗(yàn)過程是什么樣子的呢?
此代碼在DexVerify.cpp中,如下:

  1. 驗(yàn)證clazz->directMethods方法,directMethods包含了以下方法:

    • static方法

    • private方法

    • 構(gòu)造函數(shù)

  2. clazz->virtualMethods

    • 虛函數(shù)=override方法?

概括一下就是如果以上方法中直接引用到的類(第一層級關(guān)系,不會進(jìn)行遞歸搜索)和clazz都在同一個(gè)dex中的話,那么這個(gè)類就會被打上CLASS_ISPREVERIFIED:

所以為了實(shí)現(xiàn)補(bǔ)丁方案,所以必須從這些方法中入手,防止類被打上CLASS_ISPREVERIFIED標(biāo)志。
最終空間的方案是往所有類的構(gòu)造函數(shù)里面插入了一段代碼,代碼如下:
if (ClassVerifier.PREVENT_VERIFY) { System.out.println(AntilazyLoad.class); }

其中AntilazyLoad類會被打包成單獨(dú)的hack.dex,這樣當(dāng)安裝apk的時(shí)候,classes.dex內(nèi)的類都會引用一個(gè)在不相同dex中的AntilazyLoad類,這樣就防止了類被打上CLASS_ISPREVERIFIED的標(biāo)志了,只要沒被打上這個(gè)標(biāo)志的類都可以進(jìn)行打補(bǔ)丁操作。
然后在應(yīng)用啟動(dòng)的時(shí)候加載進(jìn)來.AntilazyLoad類所在的dex包必須被先加載進(jìn)來,不然AntilazyLoad類會被標(biāo)記為不存在,即使后續(xù)加載了hack.dex包,那么他也是不存在的,這樣屏幕就會出現(xiàn)茫茫多的類AntilazyLoad找不到的log。
所以Application作為應(yīng)用的入口不能插入這段代碼。(因?yàn)檩d入hack.dex的代碼是在Application中onCreate中執(zhí)行的,如果在Application的構(gòu)造函數(shù)里面插入了這段代碼,那么就是在hack.dex加載之前就使用該類,該類一次找不到,會被永遠(yuǎn)的打上找不到的標(biāo)志)
其中:

之所以選擇構(gòu)造函數(shù)是因?yàn)樗辉黾臃椒〝?shù),一個(gè)類即使沒有顯式的構(gòu)造函數(shù),也會有一個(gè)隱式的默認(rèn)構(gòu)造函數(shù)。
空間使用的是在字節(jié)碼插入代碼,而不是源代碼插入,使用的是javaassist庫來進(jìn)行字節(jié)碼插入的。
隱患:
虛擬機(jī)在安裝期間為類打上CLASS_ISPREVERIFIED標(biāo)志是為了提高性能的,我們強(qiáng)制防止類被打上標(biāo)志是否會影響性能?這里我們會做一下更加詳細(xì)的性能測試.但是在大項(xiàng)目中拆分dex的問題已經(jīng)比較嚴(yán)重,很多類都沒有被打上這個(gè)標(biāo)志。
如何打包補(bǔ)丁包:

  1. 空間在正式版本發(fā)布的時(shí)候,會生成一份緩存文件,里面記錄了所有class文件的md5,還有一份mapping混淆文件。

  2. 在后續(xù)的版本中使用-applymapping選項(xiàng),應(yīng)用正式版本的mapping文件,然后計(jì)算編譯完成后的class文件的md5和正式版本進(jìn)行比較,把不相同的class文件打包成補(bǔ)丁包。
    備注:該方案現(xiàn)在也應(yīng)用到我們的編譯過程當(dāng)中,編譯不需要重新打包dex,只需要把修改過的類的class文件打包成patch dex,然后放到sdcard下,那么就會讓改變的代碼生效。

關(guān)于安卓App熱補(bǔ)丁動(dòng)態(tài)修復(fù)技術(shù)是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。


當(dāng)前題目:安卓App熱補(bǔ)丁動(dòng)態(tài)修復(fù)技術(shù)是什么
文章路徑:http://weahome.cn/article/gdcoje.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部