android熱修複原理總結

來源:互聯網
上載者:User

標籤:

背景

當app發布之後如果出現了緊急的線上bug,整個公司都會為此忙的焦頭爛額,現公司如果線上出現嚴重的P1級bug,甚至大半夜整個項目組都得來緊急修複上線,而bug的原因可能僅僅是傳錯了參數,或者寫錯一行代碼,而且修複後的app又得重新上架,直到使用者更新後bug才會被修正。那熱修複技術的出現就能很大程度上緩解這種情況,修複後不需要重新上架,使用者也不需要重新下載安裝。

原理

github上的熱修複架構如nuwa,HotFix原理都是依據安卓App熱補丁動態修複技術介紹和Android dex分包方案
這兩篇文章,我這裡也只是對這兩篇文章做一個自己的總結加深理解。
關於nuwa架構的使用看另一篇部落格熱修複架構nuwa的使用
熱修複原理是基於Android的分包方案的,那麼什麼是Android的分包方案呢,Android2.3之前執行dexopt的記憶體只有5M,每個dex的方法數不能超過65535,當app功能複雜,類和方法特別多的時候就會在編譯時間報錯。Android dex分包方案中的描述:

當一個app的功能越來越複雜,代碼量越來越多,也許有一天便會突然遇到下列現象:

  1. 產生的apk在2.3以前的機器無法安裝,提示INSTALL_FAILED_DEXOPT

  2. 方法數量過多,編譯時間出錯,提示:

Conversion to Dalvik format failed:Unable to execute dex: method ID
not in [0, 0xffff]: 65536

出現這種問題的原因是:

  1. Android2.3及以前版本用來執行dexopt(用於最佳化dex檔案)的記憶體只分配了5M

  2. 一個dex檔案最多隻支援65536個方法。

解決辦法是將編譯好的class檔案打成兩個dex的包,運行時注入ClassLoader。如何注入呢,先看一下Android的ClassLoader體系,圖片是分包方案裡扒的。

可以看到實作類別有兩個DexClassLoader和PathClassLoader,其中PathClassLoader是用來Android用來載入Android系統類別和應用的載入器,DexClassLoader用來載入.dex和.jar中的class.dex檔案。看一下BaseDexClassLoader載入類的方法,從pathList雷根據類名找,找不到就class not found。pathList是BaseDexClassLoader中的一個對象,它包含一個dexElements集合,找類就是聽過遍曆這個集合,拿到dexFile去找類。

一個ClassLoader可以包含多個dex檔案,每個dex檔案是一個Element,多個dex檔案排列成一個有序的數組dexElements,當找類的時候,會按順序遍曆dex檔案,然後從當前遍曆的dex檔案中找類,如果找類則返回,如果找不到從下一個dex檔案繼續尋找。(來自:安卓App熱補丁動態修複技術介紹)

#BaseDexClassLoader@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {    Class clazz = pathList.findClass(name);    if (clazz == null) {        throw new ClassNotFoundException(name);    }    return clazz;}#DexPathListpublic Class findClass(String name) {    for (Element element : dexElements) {        DexFile dex = element.dexFile;        if (dex != null) {            Class clazz = dex.loadClassBinaryName(name, definingContext);            if (clazz != null) {                return clazz;            }        }    }    return null;}#DexFilepublic Class loadClassBinaryName(String name, ClassLoader loader) {    return defineClass(name, loader, mCookie);}private native static Class defineClass(String name, ClassLoader loader, int cookie);

這樣我們將有bug的類打成patch.jar然後插入到dexElements的最前邊位置,findclass的時候就會從我們的patch.jar 中開始找,找到類之後就返回,有問題的類就被補丁包中的替換掉了。之後還有一個CLASS_ISPREVERIFIED的問題,詳細可以看安卓App熱補丁動態修複技術介紹主要是說,如果類和其引用類如果不在同一個dex包裡就會報錯,校檢出這個錯的前提是引用類被打上了CLASS_ISPREVERIFIED標識,這個標識是什麼時候被打上的呢,在虛擬機器啟動的時候如果一個類的private,static,或者構造方法直接引用到的類都在同一個dex包裡就會給當前類打上這個標識,所以要阻止這個表示被打上,我們要讓類引用一個外部dex包裡的類,往所有的類的建構函式中插入一段

if (ClassVerifier.PREVENT_VERIFY) {    System.out.println(AntilazyLoad.class);}public class AntilazyLoad{}

所以我們還需要一個hack.dex,寫個空的類AntilazyLoad打成dex包,而且必須先載入這個包,否則引用這個類的地方就會class not fount,載入方法就和之前的一樣啦,要注意

Application作為應用的入口不能插入這段代碼。(因為載入hack.dex的代碼是在Application中onCreate中執行的,如果在Application的建構函式裡面插入了這段代碼,那麼就是在hack.dex載入之前就使用該類,該類一次找不到,會被永遠的打上找不到的標誌)(來自:安卓App熱補丁動態修複技術介紹)。

android熱修複原理總結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.