熱修復技術分為幾部分:
原理介紹
Android HotFix源碼分析
自定義框架
1.Android分包MultiDex原理
首先Dex是什么東西?
Dex就是Window里面的exe文件 也就是可執行問題。
Android沒有用傳統的Java虛擬機,而是使用dalvik虛擬機。當APK安裝到手機后,dalvik會先把de文件轉化位ODEX文件,
優化結構。
在早期的android系統中,為了優化dex,所有的method會存放在一張表里面,表的大小位short,也就是65535(65K)
But現在android代碼非常多,超過65K很正常,這個時候就需要一種解決方案來解決這個問題。
簡單來說就是將編譯好的class文件分拆成2個dex文件,繞過65k的限制。
關於分包的具體實現,可以參考dex分包方案概述與multidex包的配置使用
2.Android熱補丁修復技術原理
目的:有時候需要修改幾行代碼,但是我們需要重發各個市場,重新release等。是不是可以只是簡單的打patch就可以解決這個問題呢?
首先來看dex加載的源碼:
public Class findClass(String name, List<Throwable> suppressed) { for (Element element : dexElements) { DexFile dex = element.dexFile; if (dex != null) { Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed); if (clazz != null) { return clazz; } } } if (dexElementsSuppressedExceptions != null) { suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions)); } return null; }
每個element對應的就是dex文件,所以加載class就是從一個個dex文件中找到對應的code。but,可以發現,一旦找到成功了以后,就直接return。
也就是說如果2個dex含有相同的class,會先返回前面那個。
so 我們的解決方案來了,使用一個新的dex,讓他在element文件表的最前面,這樣我們修改的class文件就會被首先加載進來。
理論上,如果在不同的dex中有相同的類存在,那么會優先選擇排在前面的dex文件的類,如下圖:

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

好,該方案基於第二個拆分dex的方案,方案實現如果懂拆分dex的原理的話,大家應該很快就會實現該方案,如果沒有拆分dex的項目的話,可以參考一下谷歌的multidex方案實現。然后在插入數組的時候,把補丁包插入到最前面去。
But 我們發現在插入patch.dex后,會報錯,原因是CLASS_ISPREVERIFIED。這是個什么東東?
在類的方法中直接引用的類,如果在同一dex中,就會被打上CLASS_ISPREVERIFIED這個標志。
我們單獨給一個AntilazyLoad類打包成hack.dex 這樣每個class里面都調用。我們在構造函數里面添加:
public class A{ public A() { system.println(AntilazyLoad.class); } }
So,這樣A就引用了不在一個dex里面的class,從而不會被打上CLASS_ISPREVERIFIED的代碼。進而不會出現問題。
參考:
http://my.oschina.net/853294317/blog/308583
http://blog.csdn.net/lmj623565791/article/details/49883661
