原理
java文件打包成apk后其實(shí)就是apk里的一個(gè)個(gè)dex文件。
當(dāng)一個(gè)apk出現(xiàn)多個(gè)dex文件后,需要把dex文件塞入到app的classloader之中。如果class.dex和class1.dex中有一個(gè)類是重復(fù)的,系統(tǒng)其實(shí)并不會(huì)報(bào)異常,依然正常運(yùn)行。那系統(tǒng)會(huì)選擇加載哪個(gè)類呢?它會(huì)選擇排在前面dex的類。
讓我們來(lái)看看類加載的代碼:


當(dāng)找類的時(shí)候,會(huì)按順序遍歷dex文件,然后從當(dāng)前遍歷的dex文件中找類,如果找到類則返回,如果找不到從下一個(gè)dex文件繼續(xù)查找。
在此基礎(chǔ)上,構(gòu)想了熱修復(fù)的方案:把有問(wèn)題的類打包到一個(gè)dex(patch.dex)中去,然后把該dex插入到Element的最前面。
如下圖:

但是存在一個(gè)問(wèn)題:當(dāng)我們修改某個(gè)類,然后打包成dex,插入到classloader,當(dāng)加載類的時(shí)候,出現(xiàn)了異常。
為什么出現(xiàn)異常?
ModuleManager引用了QzoneActivityManager,但是發(fā)現(xiàn)這這兩個(gè)類所在的dex不在一起,其中:
- ModuleManager在classes.dex中
- QzoneActivityManager在patch.dex中
結(jié)果發(fā)生了錯(cuò)誤。
那么如何讓不在同一個(gè)dex中的兩個(gè)類,即使存在引用關(guān)系,也不崩潰呢?
不進(jìn)行dex校驗(yàn)~
怎么才會(huì)不做dex校驗(yàn)?zāi)兀烤褪遣灰淮蛏螩LASS_ISPREVERIFIED標(biāo)志。
具體實(shí)現(xiàn):就是在所有類的構(gòu)造函數(shù)中插入一段代碼,具體如下
if (ClassVerifier.PREVENT_VERIFY) {
System.out.println(AntilazyLoad.class);
}

只要類A沒(méi)有被打上CLASS_ISPREVERIFIED標(biāo)志,那么即使Antilazyload這個(gè)類在不同的dex中,也不會(huì)出現(xiàn)問(wèn)題。
在虛擬機(jī)啟動(dòng)的時(shí)候,當(dāng)verify選項(xiàng)被打開(kāi)的時(shí)候,如果static方法、private方法、構(gòu)造函數(shù)等,其中的直接引用(第一層關(guān)系)到的類都在同一個(gè)dex文件中,那么該類就會(huì)被打上CLASS_ISPREVERIFIED標(biāo)志。
那么,我們要做的就是,阻止該類打上CLASS_ISPREVERIFIED的標(biāo)志。
注意下,是阻止引用者的類,也就是說(shuō),假設(shè)你的app里面有個(gè)類叫做LoadBugClass,再其內(nèi)部引用了BugClass。發(fā)布過(guò)程中發(fā)現(xiàn)BugClass有編寫錯(cuò)誤,那么想要發(fā)布一個(gè)新的BugClass類,那么你就要阻止LoadBugClass這個(gè)類打上CLASS_ISPREVERIFIED的標(biāo)志。
讓LoadBugClass在構(gòu)造方法中,去引用別的dex文件,比如:hack.dex中的某個(gè)類即可。
Application作為應(yīng)用的入口不能插入這段代碼(構(gòu)造函數(shù))。
因?yàn)閔ack.dex是在onCreate中執(zhí)行的,如果插入上述代碼,會(huì)出現(xiàn)找不到Antilazyload。
QQ空間使用的是字節(jié)碼插入代碼的方式,并不是源代碼插入,借助了庫(kù)javaassist進(jìn)行字節(jié)碼插入。
QQ空間如何打補(bǔ)丁包
1.當(dāng)正式版本發(fā)布之后,會(huì)生成一個(gè)緩存文件,緩存文件中有所有class的md5以及mapping混淆文件
2.在后續(xù)版本使用了apply-mapping選項(xiàng),正式版本的mapping文件,md5文件和上個(gè)版本進(jìn)行比較,這樣就可以把不同的class打包成dex了。
插件化是什么
插件化一般就是提供一個(gè)apk(插件)文件,然后在程序中l(wèi)oad該apk,那么如何加載apk中的類呢?其實(shí)就是通過(guò)這個(gè)DexClassLoader
總結(jié)一句話
看了很多,發(fā)現(xiàn)兼容性并不太好。所以轉(zhuǎn)戰(zhàn)了~~~~重新看Tinker
參考文章
http://blog.csdn.net/lmj623565791/article/details/49883661
https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a&scene=1&srcid=1106Imu9ZgwybID13e7y2nEi#wechat_redirect
http://www.cnblogs.com/chenxibobo/p/6076459.html