Android 熱修復總結

前段時間熱修復這個詞非常火,當時只是大體看了一下,今天抽空好好看了一下具體原理.

什麼是熱修復?

簡單的說就是用戶不用重新下載一個新的apk安裝,而是直接下載一個補丁包,通過補丁來替換一些出現bug的類, 當然下載補丁的過程用戶一般是感覺不到的,表面上看是直接修復了bug.

原理

類似與插件開發,關於插件開發原理,看這篇Android插件原理剖析,其中介紹了一下java中的類加載器和android中的類加載器. 熱修復就是利用android中的 DexClassLoader類加載器,動態加載補丁dex,替換有bug的類

已有的熱修復解決方案:

這幾個庫的原理都類似,具體描述可以查看這篇安卓App熱補丁動態修復技術介紹.

切入點

想修復方法? 方法在哪裏? 方法都包含在類中. 類在哪裏? 類被包含在dex中,而

最根本的來源是下面這段代碼:

1
2
3
4
5
6
7
8
9
10
11
12
public 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;
}

可以看出呢,BaseDexClassLoader中有個pathList對象,pathList中包含一個DexFile的集合dexElements,而對於類加載呢,就是遍歷這個集合,通過DexFile去尋找,一個ClassLoader可以包含多個dex文件,每個dex文件是一個Element,多個dex文件排列成一個有序的數組dexElements,當找類的時候,會按順序遍歷dex文件,然後從當前遍歷的dex文件中找類,如果找類則返回,如果找不到從下一個dex文件繼續查找。

簡單來說: 首先找到pathList對象,然後通過反射改變dexElements數組.
但是遇到的以下問題: 也就是類被打上了 CLASS_ISPREVERIFIED 標誌

1
java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation

根據QQ空間的文章, 這個錯誤是因爲虛擬機加載類的時候, 當一個類中的直接方法(Direct Method)來自與同一個dex中,那麼這個類就會被加上 CLASS_ISPREVERIFIED 標誌, 再次通過類加載器加載會出現上面的錯誤.

解決方案: 在需要加載的類中,引用一個別的dex中的類.這樣這個類就不會被加上 CLASS_ISPREVERIFIED 標誌了,然後就可以再次加載了. 上面一個開源庫的普遍方案就是在類的 默認構造方法 上面添加一個其他dex的引用.

總結

於是總體步驟如下:

  1. 可能出現bug的類中,引用一下別的dex中的類.
  2. 因爲1中引用了別的dex,需要先將別的dex加載進來.
  3. 現在可以替換bug的類了,加載補丁,通過反射將補丁中的dex放到pathList對象的dexElements數組的前面,完成打補丁.

其中兩個注意點:

  • 防止類被加上 CLASS_ISPREVERIFIED 標誌(通過修改類默認構造方法)
  • 生成補丁dex(通過dx工具)

參考文章:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章