標籤:
熱修複技術分為幾部分:
原理介紹
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的項目的話,可以參考一下Google的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的代碼。進而不會出現問題。
參考:
安卓App熱補丁動態修複技術介紹
http://my.oschina.net/853294317/blog/308583
http://blog.csdn.net/lmj623565791/article/details/49883661
Android 熱修複技術(1)---原理