1. 程式人生 > >Android 熱修復的幾種方案對比

Android 熱修復的幾種方案對比

Dexposed是一個阿里巴巴手機淘寶基於Xposed進行的改進,產生了針對Android Dalvik 虛擬機器執行時的Java Method Hook 技術--Dexposed。

在native層中先找到要修復的Java函式對應的Method物件,修改它變為native方法,把它的nativeFunc指向hookedMethodCallback。這樣對這個java函式的呼叫就轉為呼叫hookedMethodCallback這個native函數了,然後再用這個native函式回撥java層自己實現的統一介面來處理。這個統一介面是XC_MethodReplacement類,它主要有beforeHookedMethod、afterHookedMethod和replaceHookedMethod等幾個方法,前兩個在執行原java函式前後做一些事,replaceHookedMethod則是替換原java方法。

但這個方案由於對底層Dalvik結構的過於依賴,最終無法相容Android 5.0以後的ART虛擬機器,所以現在也沒什麼卵用。

二、Andfix

Andfix 是支付寶提出的一種底層結構替換的方案,也達到了執行時即時生效的效果,並且重要的是,做到了Dalvik和ART環境的全版本相容。

實現原理: 
AndFix的原理就是方法的替換,把有bug的方法替換成補丁檔案中的方法。

這裡寫圖片描述

對於實現方法的替換,需要在Native層操作,經過三個步驟:

這裡寫圖片描述

總結該方案的優缺點: 
優點:

1.BUG修復的即時性

2.補丁包同樣採用差量技術,生成的PATCH體積小

3.對應用無侵入,幾乎無效能損耗

不足:

1.不支援新增欄位,以及修改方法,也不支援對資源的替換。

2.由於廠商的自定義ROM,對少數機型暫不支援。相容性差。

(每一個java方法在art種都對應一個ArtMethod, ArtMethod記錄了這個java方法的所有資訊,包括所屬類,訪問許可權、程式碼執行地址。 
通過evn->FromReflectedMethod,可以由Method物件得到這個方法對應的ArtMethod的真正其實地址,然後就可以把它強轉為ArtMethod指標,從而對其所有的成員進行修改。這樣就全部替換完之後就完成了熱修復邏輯。以後呼叫這個方法時就會直接走到新方法的實現中了。 
然而由於andfix裡面的ArtMethod的結構體遵照android虛擬機器art原始碼裡面的ArtMethod構建的,各個手機廠商對這個ArtMethod結構體進行修改就會導致喝原來開原始碼裡面的結構不一致,那麼在這個修改過的裝置上,替換機制就會出問題,無法正常執行熱修復邏輯。)

三、阿里百川Hotfix(@Deprecated)

阿里百川Hotfix其實是阿里手機淘寶根據對Andfix的使用,對相關業務解偶後推出的,所以Andfix的缺點它也有。而且阿里已經在此基礎上推出了更好的替代方案Sophix。所以這個這個以後基本上用不上了。

四、阿里Sophix

下面是阿里系的熱修復方案的對比。

這裡寫圖片描述

從上圖來看Sophix 應該是阿里系現在最好的了,相比其他的方案:

優點:

每個廠商的官網都不例外的說自己的方案怎麼怎麼好,下面摘自官網的介紹,根據我的試用進行了標註。

這裡寫圖片描述

總體來說最大的優勢在於:

1、補丁即時生效,不需要應用重啟;(這個聽著好像很爽,其實好多時候還是都要冷啟動才能生效,如果是資原始檔要好幾次下面是官網的圖)

這裡寫圖片描述

2、補丁包同樣採用差量技術,生成的PATCH體積小; 
3、對應用無侵入,幾乎無效能損耗; 
4、傻瓜式接入。(這個確實接入很簡單,後臺使用也簡單,生成補丁的工具也是圖形化的)

缺點: 
1、這個不開源,只能用阿里的後臺,如果你想釋出在自己的後臺那就不能用了。

五、QQ空間超級補丁技術

超級補丁技術基於DEX分包方案,使用了多DEX載入的原理,大致的過程就是:把BUG方法修復以後,放到一個單獨的DEX裡,插入到dexElements陣列的最前面,讓虛擬機器去載入修復完後的方法。

當patch.dex中包含Target.class時就會優先載入,在後續的DEX中遇到Target.class的話就會直接返回而不去載入,這樣就達到了修復的目的。

六、Tinker

微信針對QQ空間超級補丁技術的不足提出了一個提供DEX差量包,整體替換DEX的方案。主要的原理是與QQ空間超級補丁技術基本相同,區別在於不再將patch.dex增加到elements陣列中,而是差量的方式給出patch.dex,然後將patch.dex與應用的classes.dex合併,然後整體替換掉舊的DEX,達到修復的目的。

這裡寫圖片描述

整體的流程是:

這裡寫圖片描述

從流程圖來看,同樣可以很明顯的找到這種方式的特點:

優勢:

1.合成整包,不用在建構函式插入程式碼,防止verify,verify和opt在編譯期間就已經完成,不會在執行期間進行。

2.效能提高。相容性和穩定性比較高。

3.開發者透明,不需要對包進行額外處理。

不足:

1.與超級補丁技術一樣,不支援即時生效,必須通過重啟應用的方式才能生效。

2.需要給應用開啟新的程序才能進行合併,並且很容易因為記憶體消耗等原因合併失敗。

3.合併時佔用額外磁碟空間,對於多DEX的應用來說,如果修改了多個DEX檔案,就需要下發多個patch.dex與對應的classes.dex進行合併操作時這種情況會更嚴重,因此合併過程的失敗率也會更高。

七、Amigo

八、Robust

Robust外掛對每個產品程式碼的每個函式都在編譯打包階段自動的插入了一段程式碼,插入過程對業務開發是完全透明。在Application中通過DexClassLoader,將補丁class檔案事先載入,然後之後會呼叫新的class以替換舊apk中的bug class檔案,通過反射進行新程式碼的呼叫,以達到熱修復目的。大致流程如下圖

這裡寫圖片描述

優點: 
1、高相容和適配性,由於是java程式碼層面的替換呼叫,基本不涉及各個版本的適配和虛擬機器的適配。 
缺點: 
1、由於對包體中的檔案進行了程式碼侵入,對執行效率、方法數、包體積都有影響,檔案方法數變多,企業級應用可能會涉及到65535的問題。 
2、專案不夠成熟,文件不夠健全。