<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] Hotfix方案分為三種: 1. 類加載方案(Tinker) 2. 底層替換方案(Sophix) 3. InstantRun方案(Robust) 三種典型的方案特點如下: | 方案對比 | Sophix | Tinker | Robust | | --- | --- | --- | --- | | DEX修復 | 同時支持即時生效和冷啟動修復 | 冷啟動修復 | 即時成效 | | 資源更新 | 差量包,不用合成 | 差量包,需要合成 | 差量包 | | SO庫更新 | 插樁實現,開發透明 | 替換接口,開發不透明 | 不支持 | | 性能損耗 | 低,僅冷啟動情況下有些損耗 | 高,有合成操作 | 低 | | 四大組件 | 不能新增 | 不能新增 | 不能新增 | | 生成補丁 | 直接選擇已經編好的新舊包在本地生成 | 編譯新包時設置基線包 | 編譯新包時設置基線包 | | 補丁大小 | 小 | 小 | 小 | | 接入成本 | 傻瓜式接入 | 復雜 | 一般,文件服務器需要自己實現 | | Android版本 | 全部支持 | 全部支持 | 全部支持 | | 安全機制 | 加密傳輸及簽名校驗 | 加密傳輸及簽名校驗 | 自己實現 | | 服務端支持 | 支持服務端控制 | 支持服務端控制 | 自己實現 | ### 美團Robust 原理介紹可以看這里:[Android熱補丁之Robust原理解析(一)](http://w4lle.com/2017/03/31/robust-0/) 類似于 InstantRun 熱插拔的機制,在打基準包時為每類插入了一個`ChangeQuickRedirect`靜態變量,并為每個方法插入了一段代理邏輯。當打上補丁后,靜態變量不為空,這樣就會調用代理方法,以此實現了熱修復的功能。示例代碼如下: ~~~ public static ChangeQuickRedirect u; protected void onCreate(Bundle bundle) { if (u != null) { if (PatchProxy.isSupport(new Object[]{bundle}, this, u, false, 78)) { PatchProxy.accessDispatchVoid(new Object[]{bundle}, this, u, false, 78); return; } } super.onCreate(bundle); ... } ~~~ 其主要流程中涉及到的點如下: 1. 打基準包:根據配置使用Javassit或者ASM為每個類進行插樁。 2. 打補丁包:掃描Modify、Add注釋修飾的方法,為對應的類生成補丁。 3. 安裝補丁:使用DexClassLoader加載補丁,加載完畢后反射得到特定的補丁入口類,并創建其對象。補丁入口類里面定義了需要修改的基準類以及對應的熱修復ChangeQuickRedirect實現類。得到哪些修改的基準類后,再通過反射循環拿到每個基準類的class,將其中類型為 ChangeQuickRedirect 的靜態變量反射修改為 補丁包中生成的熱修復實現類。 ![Robust](https://blog.yorek.xyz/assets/images/android/robust.png) 優點: * 由于使用多ClassLoader方案(補丁中無新增Activity,所以不算激進類型的動態加載,無需hook system),**兼容性和穩定性更好**,不存在preverify的問題 * 由于采用 InstantRun 的熱更新機制,所以可以即時生效,**不需要重啟** * 支持Android2.3-10版本 * 對性能影響較小,不需要合成patch * 支持方法級別的修復,支持靜態方法 * 支持新增方法和類 * 支持ProGuard的混淆、內聯、編譯器優化后引起的問題(橋方法、lambda、內部類等)等操作 當然,有優點就會有缺點: * 暫時不支持新增字段,但可以通過新增類解決 * 暫時不支持修復構造方法,已經在內測 * **暫時不支持資源和 so 修復**,不過這個問題不大,因為獨立于 dex 補丁,已經有很成熟的方案了,就看怎么打到補丁包中以及 diff 方案。 * 對于返回值是 this 的方法支持不太好 * 沒有安全校驗,需要開發者在加載補丁之前自己做驗證 * 可能會出現深度方法內聯導致的不可預知的錯誤(幾率很小可以忽略) ### 2\. Sophix 相關文檔 [《深入探索Android熱修復技術原理》](https://yq.aliyun.com/articles/115122?spm=a2c4g.11186623.0.0.3afd1f05wgVPnD) [業界首個非侵入式熱修復方案Sophix重磅推出,顛覆移動端傳統更新流程!](https://developer.aliyun.com/article/103527) [Android熱修復升級探索——追尋極致的代碼熱替換](https://developer.aliyun.com/article/74598) [Android熱修復升級探索——資源更新之新思路](https://developer.aliyun.com/article/96378) [Android熱修復升級探索——Dalvik下冷啟動修復的新探索](https://developer.aliyun.com/article/107396) #### 2.1 代碼修復 Sophix的代碼修復采用了底層替換方案,時效性最好,加載輕快,立即見效。 Java中的Method在ART虛擬機中對應一個ArtMethod指針,ArtMethod結構體中包含了Java方法的所有信息,包括執行入口、訪問權限、所屬類和代碼執行地址等。 替換ArtMethod結構體中的字段或者替換整個ArtMethod結構體,這就是**底層替換方案**。 AndFix采用的是替換ArtMethod結構體中的字段,這樣會有兼容性問題,因為廠商可能會修改ArtMethod結構體,導致方法替換失敗。 Sophix采用的是替換整個ArtMethod結構體,這樣不會存在兼容問題。 此外,Sophix也有類加載方案。這時需要冷啟動才會生效。 #### 2.2 資源修復 目前市面上的很多資源熱修復方案基本上都是參考了Instant Run的實現。實際上,Instant Run的推出正是推動這次熱修復浪潮的主因,各家熱修復方案,在代碼、資源等方面的實現,很大程度上地參考了Instant Run的代碼,而資源修復方案正是被拿來用到最多的地方。 簡要說來,Instant Run中的資源熱修復分為兩步: 1. 構造一個新的AssetManager,并通過反射調用addAssetPath,把這個完整的新資源包加入到AssetManager中。這樣就得到了一個含有所有新資源的AssetManager。 2. 找到所有之前引用到原有AssetManager的地方,通過反射,把引用處替換為AssetManager。 對于補丁中的id一樣的資源,直接addAssetPath最后是沒有效果的。所以這里**構造了一個package id為0x66的資源包,這個包里只包含改變了的資源項,然后直接在原有AssetManager中addAssetPath這個包就可以了**。由于補丁包的package id為0x66,不與目前已經加載的0x7f沖突,因此直接加入到已有的AssetManager中就可以直接使用了。 **L版本上這樣就夠了,但是在Android KK和以下版本,addAssetPath是不會加載資源的,必須重新構造一個新的AssetManager并加入patch,再換掉原來的。**所以這里可以先析構在重新初始化,native層會重新執行一遍流程。 #### 2.3 so修復 so庫的修復本質上是對native方法的修復和替換。采用的是類似類修復反射注入方式。把補丁so庫的路徑插入到nativeLibraryDirectories數組的最前面,就能夠達到加載so庫的時候是補丁so庫,而不是原來so庫的目錄,從而達到修復的目的。 不過Sohpix也對so的及時生效方面做了一定的探索: * **針對動態注冊的so,可以做到及時生效**。不對Dalvik虛擬機上有一個bug導致第二次load的so不生效。因此需要對補丁so進行改名。 * **針對靜態注冊的so,需要先對影響到的類進行解注冊操作,但能難知道哪些類受到了影響**。其次,就算解決了前者,在加載補丁so之后,由于so信息保存在虛擬機中的Hashtable(采用開放定址法)中,會有補丁so可能出現在原始so之前的情況,因此加載補丁so也不會生效。 因此,Sophix最后采用了冷啟動生效的方式,方案還是有兩種: 1. 接口調用替換方案 SDK提供統一的so加載方法,內部會先嘗試加載補丁中的so,不行再調用`System.loadLibrary`方法。此方案缺點是對業務方有侵入性。 2. 反射注入方案 將補丁so庫的路徑插入到nativeLibraryDirectories數組的最前面,就能夠達到加載so庫的時候是補丁so庫 ### 3.Tinker #### 3.1 代碼修復 利用類加載機制,將合成好的補丁dex插入到DexPathList中elements數組的最前面,這樣查找類的時候就會先加載補丁中的類。 但是這里注意一下,這里的補丁都采用了diff算法來達到patch文件輕量的目錄,針對dex自研了DexDiff算法,其作用域是指令級別的。差分dex在客戶端會經過合成來變成一個全量的dex。 #### 3.2 資源修復 InstantRun的原理:還是通過AssetManager#addAssetPath來添加補丁中的resources文件,**但是這樣不會直接生效**。因此會重新創建一個AssetManager并更新所有的引用處。 注意這里對資源的修改,會比較生成的資源補丁文件的大小,超過配置的值則會采用bsdiff算法,否則不會采用。 #### 3.3 so修復[?](https://blog.yorek.xyz/android/3rd-library/hotfix/#33-so "Permanent link") Tinker對so的修復沒有直接把so插入到nativeLibraryDirectories數組的最前面,原因是“我們并沒有為你區分abi(部分手機判斷不準確)”,所以無法獲取到具體的與架構相關的so。 Tinker提供了`TinkerApplicationHelper#loadArmV7aLibrary`、`TinkerApplicationHelper#loadArmLibrary`方法加載library。里面的邏輯是嘗試先從patch中找到對應的library,然后調用`System.load(String filename)`方法加載。如果找不到,則還是調用系統的`System.loadLibrary(libName)`。 ## QFix ### 基本原理 DexClassLoader當找類的時候,會按順序遍歷dex文件,然后從當前遍歷的dex文件中找類,如果找類則返回,如果找不到繼續從下一個dex文件查找。理論上,如果在不同的dex中有相同的類存在,那么會優先選擇排在前面的dex文件的類,Qzone方案的靈感就是從上述的DexPathList類中的for循環體而來。 ![](https://img.kancloud.cn/5d/5b/5d5b818429599a0e9a0812e166f0d0c4_1076x682.png) 在此基礎上,Qzone 團隊構想了熱補丁的方案,把有問題的類打包到一個dex(patch.dex)中去,然后把這個dex插入到Elements的最前面,如下圖: ![](https://img.kancloud.cn/cb/d9/cbd94c3e9734c94cc01b9502e99a4269_1142x685.png) 如果懂拆分dex的原理的話,大家應該很快就會實現該方案。如果沒有拆分dex的項目的話,可以參考一下谷歌的multidex方案實現,然后在插入數組的時候,把補丁包插入到最前面去。 當patch.dex中包含Main.class時就會優先加載,在后續的DEX中遇到Main.class的話就會直接返回而不去加載,這樣就達到了修復的目的。### Sophix ### unexpected DEX 如果**兩個相關聯的類在不同的dex**中就會報錯,但是拆分dex沒有報錯這是為什么,原來這個校驗的前提是:如果引用者(也就是ModuleManager)這個類被打上了CLASS\_ISPREVERIFIED標志,那么就會進行dex的校驗 ![](https://img.kancloud.cn/0b/d1/0bd1b3abba708b9106af3c65f5ee24e5_640x316.png) # 參考資料 [QFix探索之路——手Q熱補丁輕量級方案](https://mp.weixin.qq.com/s/ce22vVN5zyqY0vAkNt1DDw)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看