1. 程式人生 > >全面了解Android熱修復技術

全面了解Android熱修復技術

服務 補丁 按順序 體積 及其 試用 sta x文件 犯錯

WeTest 導讀

本文探討了Android熱修復技術的發展脈絡,現狀及其未來。


熱修復技術概述

熱修復技術在近年來飛速發展,尤其是在InstantRun方案推出之後,各種熱修復技術競相湧現。國內大部分成熟的主流APP都擁有自己的熱修復技術,像手淘、支付寶、QQ、餓了麽、美團等等。

目前能搜集到的資料,大多簡單羅列每個方案的特點並進行橫向比較,而其中技術發展的脈絡往往被掩蓋了。熱修復技術從何而來,又將往何處去?在這些資料中都找不到答案。

我認為,走馬觀花地看一遍各家的熱修復方案並不能找到答案,所以寫下本文,希望從一個不同的角度來了解熱修復技術,權當拋磚引玉,如有不足,歡迎指正。

代碼熱修復

代碼熱修復是最常見,也是熱修復中最重要的部分,因為程序錯誤往往都是代碼邏輯的錯誤。最初的熱修復方案也僅支持代碼熱修復。代碼熱修復分兩個流派,即騰訊系的類加載方案和阿裏系的底層替換方案,前者需要重啟應用但卻能修復大部分錯誤,後者及時生效卻只能作方法內的修改。下面詳細介紹。

一、類加載方案

1、Qzone
Qzone的超級熱修復方案是業界最早的熱修復方案之一,原理簡單而巧妙,影響深刻而久遠,在此簡單介紹。Android類加載的源碼如下:
技術分享

可以看出當有多個dex文件時,他們會組成一個有序數組,按順序加載,而對於一個已經加載的Class是不會再次加載的,由此得出熱修復方案:把需要修復的類打包成一個dex文件下發,並在APP啟動時通過反射,將這個dex文件放在dexElements的最前面,這樣修復了的Class就會比有Bug的Class優先加載了。如下圖所示:
技術分享

但在實現過程中,會遇到unexpected DEX problem異常,Qzone方案為了解決這個問題采用了插樁的策略來規避這個異常。實際上,Android系統的檢查和優化都是有其意義的,因此這種方法在Dalvik和Art上都會遇到問題。

● 在Dalvik虛擬機,APP在安裝的時候會被執行dexopt操作,同一個dex文件內的Class會被打上CLASS_ISPREVERIFIED標誌,而補丁包中的類並沒有打上此標誌,因此拋出異常。解決方法就是在第一次打包APK時讓所有類都引用另一個dex文件中的類,這樣所有的類始終不會打上CLASS_ISPREVERIFIED標誌,因此補丁包可以順利加載,但是Dalvik虛擬機在檢測到一個類未打上CLASS_ISPREVERIFIED之後會再次在類加載的時候進行dexopt相關的操作,如果一次性加載很多類,速度將明顯變慢。

● 在Art虛擬機,dex文件最終會編譯成本地機器碼,在dex2oat時fast *已經將各個類的地址寫死,若補丁包中的類出現字段或者方法的修改,會出現內存地址錯亂,解決辦法是將這個類的父類和調用這個類的類都加入補丁包。但這樣會導致補丁包急劇增大。(實際上要理解清楚這個問題需要熟悉Dalvik和Art的完整流程,並非三言兩語能解釋清楚)

這兩個問題都可以解決,但都要付出一些代價:類加載速度或者補丁包大小。

2、Tinker
如果Qzone沒有上面兩個缺陷,或許就不會有Tinker了。對於微信這樣一個對性能有極高要求的產品來說,Qzone的缺點會被無限放大。在參考Instant Run的冷插拔與buck的exopackage後,Tinker采用了全量替換的策略。全量替換可以避免插樁和地址寫死問題,但是補丁包會很大,因此可以在新舊兩個Dex的差異放在補丁包中,下發到移動端後再在本地合成完整的dex文件。

實際上,Tinker保留了Qzone最核心的東西:反射修改dexElements。無論是插入還是替換,本質都是利用了類加載的特點。由於需要下發的全量補丁包體積過大,Tinker采用了後臺求diff,下發diff文件,移動端合成全量包的策略。

如果僅此而已,只要有diff/patch算法,就可以開發Tinker了。實際上,確實如此。而Tinker第二個創新之處就是采用了自研的DexDiff算法,大大優化了下發差異包的大小。

二、底層替換方案

阿裏的Andfix熱修復方案是底層替換方案的代表,與Qzone和Tinker的思想完全不同,Andfix通過修改一個方法的入口地址來達到修復。以Dalvik虛擬機為例,Andfix的核心代碼如下:
技術分享

其實就是修改了方法包括入口地址在內的每一項數據的地址,使之指向一個新的方法。在後臺,使用Andfix提供的apkpatch工具,可以得到補丁文件out.apatch,這個文件記錄了哪些方法需要修改,以及修改後的方法。Andfix效果:
技術分享

(註意我一直在點擊,下發補丁後發生了變化……)

資源修復

除了代碼熱修復,資源熱修復也很常見。各大主流方案在資源修復的實現上大多參考了InstantRun的實現方式,因此本章節先討論了InstantRun,再分析了基於InstantRun所實現的熱修復。

一、InstantRun

InstantRun在AndroidStudio2.0.0中引入。

InstantRun包括代碼修復和在資源修復,資源修復的核心代碼:
技術分享

技術分享

技術分享

技術分享

其實做了兩件事:
1. 通過反射替換掉原有的AssetManager
2. 找到引用了原AssetManager對象的字段並替換為新的引用。

關鍵是要熟悉Android相關源碼,才能確定哪些字段是需要更新引用的。通過以上兩步即可實現資源替換。

二、資源熱修復實現

將InstantRun的monkeyPatchExistingResource方法引入我們的代碼就可以實現資源熱修復,效果如下:

技術分享

SO庫熱修復

so庫的修復本質是對native方法的修復和替換,和類加載方案類似,可以把補丁so庫的路徑插入到nativeLibraryDirectories數組的最前面,使得優先加載補丁庫而不是原來的庫來達到修復目的。在此不做贅述。

熱修復的穩定性

一、兼容的困境

最初Qzone就需要在Dalvik平臺進行插樁,Tinker同樣也是分平臺合成(在Dalvik平臺合成全量Dex,在Art平臺合成需要的小Dex),而阿裏的Andfix作為底層熱修復方案,不僅要面對兩種虛擬機平臺,甚至要為不同Android版本編寫一套替換邏輯,如下:
技術分享

二、不安全的代碼

加載了補丁包的程序本質還是未編譯的程序,只是兩個已編譯程序的結合體,由於Java的編譯過程對於我們是透明,所以我們一不小心就會引入錯誤,而且這種錯誤十分隱蔽。在使用類加載方案時由於還是在Java層,可能不那麽容易犯錯,但使用Andfix等底層熱修復方案時卻總是防不勝防。

比如,Java在編譯匿名內部類時會編譯成頂級類,命名方式為ClassNamenniClassNamei#methodName變成ClassName$i+1#methodName,即一個方法的地址發生改變。再比如,Java的泛型編譯可能會在編譯期引入新的方法,也會導致Andfix的異常。
因為編譯過程是透明的,所以熱修復後的程序不能代替修復問題後重新編譯出來的程序,即熱修復後程序的安全性是得不到保證的。

熱修復技術展望

Qzone時期插樁影響了類加載的速度,Tinker的DexDiff算法粒度過細、實現復雜,導致性能消耗嚴重,Andfix使用場景有限、兼容性差,此外美團的Robust、餓了麽的Amigo等也都各有限制。Android熱修復技術雖然百花齊放,但卻並沒有哪種方案能夠解決所有問題,統一當前的局面。而最近阿裏又推出了Sophix,針對各種類型的修復又做了深度的優化,雖然沒有開源代碼,但是發布了《深入探索Android熱修復技術原理》,引起Android社區的關註,其統一各種熱修復方案的意圖也十分明顯。

從Qzone到Tinker,從Andfix到Sophix都可以看出來,熱修復技術還在不斷上升發展,每一次新方案的推出都是對原有方案的超越。但目前來看,阿裏並未打算開源Sophix,而Tinker2.0仍然在路上,熱修復技術在性能、兼容、開發透明方面仍然有很多不足,所以不能僅僅滿足於了解已有方案,還要深入源碼去理解原理,更要對業界最新進展保持關註。


參考:

1、安卓App熱補丁動態修復技術介紹
2、微信Tinker的一切都在這裏,包括源碼(一)
3、alibaba/AndFix: AndFix is a library that offer hot-fix for Android App.
4、Instant Run: How
5、微信Android熱補丁實踐演進之路
6、Tencent/tinker: Tinker is a hot-fix solution library for Android, it ……

騰訊WeTest兼容性測試團隊積累了10年的手遊測試經驗,旨在通過制定針對性的測試方案,精準選取目標機型,執行專業、完整的測試用例,來提前發現遊戲版本的兼容性問題,針對性地做出修正和優化,來保障手遊產品的質量。目前該團隊已經支持所有騰訊在研和運營的手遊項目。

iPhone8/iPhoneX新機即將同步上線,歡迎進入:http://wetest.qq.com/product/expert-compatibility-testing 使用專家兼容測試服務。 WeTest兼容性測試團隊期待與您交流!You Create,We Test!

如果對使用當中有任何疑問,歡迎聯系騰訊WeTest企業qq:800024531

全面了解Android熱修復技術