熱修復(fù)選型:
目前國(guó)內(nèi)主流的兩種熱修復(fù)策略有以下兩種:以阿里系為主的底層method修復(fù)方案(Hotfix);基于修改dex結(jié)構(gòu)的tx系類加載方案(Tinker)。-----阿里于17年推出的sophix方案其實(shí)是兩個(gè)方案的集合體。
局限性和優(yōu)劣性我借住以下圖標(biāo)來(lái)做個(gè)說(shuō)明:
tinker是我目前學(xué)習(xí)使用的主流框架,主要原因在于其穩(wěn)定性以及全面性,在實(shí)際開發(fā)中用于一些非緊急bug修復(fù),以及作為緊急bug修復(fù)發(fā)版的輔助項(xiàng)。
先來(lái)聊一聊andfix(MethodHotFix)的使用感受吧,不穩(wěn)定,不穩(wěn)定,不穩(wěn)定,重要的事情說(shuō)三遍!!!!!在任何一個(gè)生產(chǎn)項(xiàng)目中,穩(wěn)定性是衡量技術(shù)方案的最主要因素。
1:MethodHotFix基于規(guī)范的虛擬機(jī)底層,動(dòng)態(tài)修改和擴(kuò)展method,而國(guó)內(nèi)各大廠商又會(huì)對(duì)底層做一定的定制修改,這樣很容易導(dǎo)致失敗。
2:app運(yùn)行時(shí),類結(jié)構(gòu)已經(jīng)固化在內(nèi)存中,其動(dòng)態(tài)屬性很難擴(kuò)展;
3: ?底層替換方案是在已經(jīng)加載的類中,直接替換原有方法,在原有類上進(jìn)行修改。因而無(wú)法進(jìn)行字段和方法的增減。因?yàn)檫@樣會(huì)修改原有類的結(jié)構(gòu)。舉例:方法新增或者刪除,會(huì)導(dǎo)致這個(gè)類或者整個(gè)Dex方法數(shù)修改,方法數(shù)的修改會(huì)導(dǎo)致方法索引的修改,這樣在訪問(wèn)方法時(shí),就無(wú)法訪問(wèn)正確的索引了。字段的增減會(huì)導(dǎo)致字段索引變更,如果一個(gè)類新增了某個(gè)字段,由新方法訪問(wèn)已經(jīng)聲明的未修改前的實(shí)例對(duì)象,就難以預(yù)知會(huì)發(fā)生什么。。
底層替換方案主要是依賴修改虛擬機(jī)方法實(shí)體的具體字段。
如修改Dalvik方法的 jni 函數(shù)指針,改類或者方法的訪問(wèn)權(quán)限等。
art虛擬機(jī)中,每一個(gè)Java方法在art中都對(duì)應(yīng)著一個(gè)ArtMethod,ArtMethod記錄了這個(gè)Java方法的所有信息,包括所屬類、訪問(wèn)權(quán)限、代碼執(zhí)行地址等等。而andfix根據(jù)標(biāo)準(zhǔn)的ArtMethod進(jìn)行修改,然而各大廠商又可能修改了底層的ArtMethod,這樣通用的替換機(jī)制就會(huì)出現(xiàn)問(wèn)題。
數(shù)組優(yōu)化,不理解
類加載方案:代表作Tinker,冷啟動(dòng),需要重啟生效
類加載方案,是app在重啟后,讓classLoader去加載新類。在app運(yùn)行中,需要修改的類已經(jīng)加載過(guò)了,android是無(wú)法將一個(gè)類進(jìn)行卸載的。不重啟的話,原有的類還在虛擬機(jī)中,無(wú)法加載新類。
QQ空間方案需要侵入打包過(guò)程,為了支持hack會(huì)添加一些無(wú)用信息,不夠優(yōu)雅。QFix修復(fù)方案需要獲取底層虛擬機(jī)函數(shù),不夠穩(wěn)定可靠,且無(wú)法新增public函數(shù)。
Tinker是完整的全量替換dex方案,通過(guò)DexDiff算法的實(shí)現(xiàn),我們既解決了Dalvik平臺(tái)的性能損耗問(wèn)題,又解決了Art平臺(tái)補(bǔ)丁包過(guò)大的問(wèn)題。但這套方案的缺點(diǎn)在于占Rom體積比較大,微信考慮到移動(dòng)設(shè)備的存儲(chǔ)空間提升比較快,增加幾十M的Rom空間這個(gè)代價(jià)可以接受。
sophix,阿里最新的熱修復(fù)方案,在類加載實(shí)現(xiàn)中,也是采用dex全量替換的過(guò)程,但是顆粒主要是在類維度上。