深入探索Android熱修復技術原理讀書筆記——第一章:熱修復技術介紹
第一章 熱修復技術介紹
1.1 什麼是熱修復
傳統開發流程:
- 重寫釋出版本代價太高
- 使用者下載安裝成本太高
- bug修復不及時,使用者體驗差
有許多開發者找到了合適的解決辦法,比如:
- 經常變更的業務用H5獨立出來,但是增加了學習成本,並且無法轉為H5的程式碼還是無法修復
- 用外掛化的方案,但是學習外掛化工具需要的成本也高,對老程式碼的改造也不是短時間就能完成的
熱修復技術:
- 無需重新發版,實時高效熱修復
- 使用者無感知修復,無需下載新的應用,代價小
- 修復成功率高,把損失降到最低
1.2 技術沉澱
阿里系:
- Dexposed:基於Xposed改進,針對Android Dalvik虛擬機器執行的Java Method Hook技術,但無法相容Android5.0以後的虛擬機器
- Andfix:也是一種底層替換的方案,做到了Dalvik和ART的相容
- Hotfix:結合實際工程中的使用Andfix的經驗,推出阿里百川Hotfix,但只提供了程式碼層面的修復,對於資源和so的修復還未實現
- Sophix:2017年6月推出Sophix,打破了各家紛爭的局面,在程式碼修復,資源修復,so修復方面,都做到了業界領先
其他著名的熱修復,但是各自有各自的侷限性,補丁過大,效率低下,不夠穩定,用起來繁瑣:
- 騰訊QQ空間的超級補丁
- 微信的Tinker
- 餓了麼的Amigo
- 美團的Robust
1.3 詳細比較
Sophix和Tinker與Amigo的比較:
各項指標都佔優,唯一不支援的就是四大元件的修復
1.4 技術概覽
1.4.1 設計理念
Sophix的設計理念,就是非侵入性
- 最終的實現只有兩個生成的新舊apk,唯一要做的就是初始化和請求補丁兩行程式碼
- 不會侵入apk的build流程中
- 不改變任何打包元件
- 不插入任何AOP程式碼
1.4.2 程式碼修復
兩大方案:
- 阿里系的底層替換,限制很多,但時效性好,載入輕快,立即見效
- 騰訊系的類載入,需要重新冷啟動才能生效,但修復範圍廣,限制少
底層替換方案:
- 在原有類的基礎上進行修改,無法對原有類的方法和欄位進行增減,方法數的變化伴隨著方法索引的變化,這樣在訪問方法的時候就無法正常地索引到正確的方法了,因為增減會導致無法索引到正確的方法和欄位
- 更為嚴重的就是,比如程式正在執行中,突然某個類加了一個欄位,那有可能在之前已經產生了這個類的一箇舊的例項,那麼新方法用到這個舊的例項物件,去訪問新的欄位,那麼會產生不可預期的結果
- 最最令人詬病的是底層替換的不穩定性,傳統的底層替換方式,都是去直接依賴修改虛擬機器方法實體的具體欄位,比如,改Dalvik方法的jni函式指標、改類或方法的訪問許可權等,這有一個很嚴重的問題,由於Android的碎片化,是開源的,不同的手機廠商可能會對這個ArtMethod結構體進行了修改,那麼在這些修改過原始碼的裝置上,通用性的替換機制就會出問題。這是不穩定的根源
- 只要保證ArtMethod陣列仍是以線性結構排列,就能直接使用於將來的Android8.0,9.0等新版本
類載入方案:
- 在app重新啟動後讓Classloader去載入新的類,因為在app執行到一半的時候,所有需要發生變更的類已經被載入過了,只有在下次重啟的時候,還沒走到業務邏輯之前搶先載入補丁中的新類
- QQ空間方案會侵入打包流程、QFix的方案需要獲取底層虛擬機器的函式,不夠穩定可靠,並且無法新增public函式、微信的Tinker方法是完整的全量dex載入,可以很大的節省空間,但是效能消耗比較嚴重,因此,Tinker方案的時空代價轉換的價效比並不高
- 阿里採用的也是全量合成dex的技術,直接利用Android原先的類查詢和合成機制,快速合成新的全量dex,這樣既不需要處理合成時方法數超過的情況,對於dex的機構也不用進行破壞性重構。重新編排了包中的dex的順序,大大減少合成補丁的開銷
雙劍合璧:
- Sophix的程式碼修復體系正是同事涵蓋了這兩種方案,兩種方案的結合,實現優勢互補,完全兼顧的作用
- 在補丁生成階段,會根據實際程式碼變動情況進行自動選擇,小修改,在底層替換方案的限制內,直接用底層替換方案修復,這樣還可以做到程式碼修復即生效,對於超出底層替換限制的,就使用類載入替換,另外,執行時階段,Sophix還會判斷所執行的機型是否支援底層替換,不支援就走類載入修復,達到更好的相容性
1.4.3 資源修復
目前市面上的很多資源熱修復方案基本上都是參考了Instant Run的實現
Instant Run中的資源熱修復分為兩步:
- 構造一個新的AssetManager,並通過反射呼叫addAssetPath,把這個完整的新資源包加入到AssetManager中,這樣就得到了一個含有所有新資源的AssetManager。
- 找到所有之前引用到原有AssetManager的地方,通過反射,把引用處替換為AssetManager
阿里的方案:構造了一個package id為0x66的資源包,這個包裡只包含了改變了的資源項,然後在原有的AssetManager中addAssetPath這個包就可以了。補丁包裡面的資源,只包含原有包裡面沒有新的包裡面有的新增資源,以及原有內容發生了改變的資源。採用了更加優雅的替代方式,直接在原有的AssetManager物件上進行析構和重構,這樣所有原先對AssetManager物件的引用是沒有發生改變的,所以就不需要像Instant Run那樣進行繁瑣的修改了
阿里資源修復方案的優勢在於:
- 不修改AssetManager的引用處,替換更快更完全
- 不必下發完整包,補丁包中只包含有變動的資源
- 不需要再執行時合成完整包。不佔用執行時計算和記憶體資源
1.4.4 SO庫修復
SO庫修復本質上是對native方法的修復和替換
阿里採用的是類似類修復反射注入方式,把補丁so庫的路徑插入到nativeLibraryDirectories陣列的最前面,達到載入so庫的時候是補丁so庫,而不是原來so庫的目錄,從而達到修復目的。
1.5 本章小結
本章介紹了熱修復技術的主要使用場景和為業界帶來的變化,詳細說明了阿里巴巴推出的熱修復解決方案Sophix的由來,以及和其他各大主流方案進行了比較
總結
這章是本書的第一章,不過讀起來還是蠻受用的,大體瞭解了現在熱修復技術趨勢和藥店,內容大都是概念性的,有一部分地方肯定不可能看看簡述就能明白的,那麼需要在接下來的幾章內容好好來探索一番,覺得這本書真的挺不錯的!