2018深入解析Android熱修復技術

android飛魚發表於2018-11-15

本文框架

  • 什麼是熱修復?
  • 熱修復框架分類
  • 技術原理及特點
  • Tinker框架解析
  • 各框架對比圖
  • 總結

通過閱讀本文,你會對熱修復技術有更深的認知,本文會列出各類框架的優缺點以及技術原理,文章末尾簡單描述一下Tinker的框架結構。

一、什麼是熱修復?

正常開發流程

2018 深入解析Android熱修復技術

 

熱修復開發流程

2018 深入解析Android熱修復技術

 

熱修復優勢

2018 深入解析Android熱修復技術

 

修復什麼?

2018 深入解析Android熱修復技術

 

二、熱修復框架分類

現狀:百花齊放百家爭鳴

2018 深入解析Android熱修復技術

 

簡單分類

2018 深入解析Android熱修復技術

 

更合理的分類

2018 深入解析Android熱修復技術

 

三、技術原理及特點

3.1 阿里Dexposed — native解決方案

原理:

  • 直接在native層進行方法的結構體資訊對換,從而實現完美的方法新舊替換,從而實現熱修復功能

他的思想完全來源於Xposed框架,完美詮釋了AOP程式設計,這裡用到最核心的知識點就是在native層獲取到指定方法的結構體,然後改變他的nativeFunc欄位值,而這個值就是可以指定這個方法對應的native函式指標,所以先從Java層跳到native層,改變指定方法的nativeFunc值,然後在改變之後的函式中呼叫Java層的回撥即可。實現了方法的攔截功能。

  • 基於開源框架Xposed實現,是一種AOP解決方案
  • 只Hook App本身的程式,不需要Root許可權

2018 深入解析Android熱修復技術

 

2018 深入解析Android熱修復技術

 

2018 深入解析Android熱修復技術

 

優點:

  • 即時生效
  • 不需要任何編譯器的插樁或者程式碼改寫,對正常執行不引入任何效能開銷。這是AspectJ之類的框架沒法比擬的優勢;
  • 對所改寫方法的效能開銷也極低(微秒級),基本可以忽略不計;
  • 從工程的角度來看,熱補丁僅僅是牛刀小試,它真正的威力在於『線上除錯』;
  • 基於Xposed原理實現的AOP不僅可以hook自己的程式碼,還可以hook同程式的Android SDK程式碼,這也就可以讓我們有能力在App中填上Google自己挖的坑。

缺點:

  • Dalvik上近乎完美,不支援ART(需要另外的實現方式),所以5.0以上不能用了;
  • 最大挑戰在於穩定性與相容性,而且native異常排查難度更高;
  • 由於無法增加變數與類等限制,無法做到功能釋出級別;

3.2 阿里AndFix — native解決方案

原理:

  • 與Dexposed一樣都基於開源框架Xposed實現,是一種AOP解決方案

優點:

  • 即時生效
  • 支援dalvik和art(AndFix supports Android version from 2.3 to 7.0, both ARM and X86 architecture, both Dalvik and ART runtime, both 32bit and 64bit.)
  • 與Dexposed框架相比AndFix框架更加輕便好用,在進行熱修復的過程中更加方便了

缺點:

  • 面臨穩定性與相容性問題
  • AndFix不支援新增方法,新增類,新增field等

AndFix(Dexpsed)框架不穩定的原因(痛點)

2018 深入解析Android熱修復技術

 

2018 深入解析Android熱修復技術

 

原理:

  • 原理是Hook了ClassLoader.pathList.dexElements[]。因為ClassLoader的findClass是通過遍歷dexElements[]中的dex來尋找類的。當然為了支援4.x的機型,需要打包的時候進行插樁。
  • 越靠前的Dex優先被系統使用,基於類級別的修復

2018 深入解析Android熱修復技術

 

優點:

  • 不需要考慮對dalvik虛擬機器和art虛擬機器做適配
  • 程式碼是非侵入式的,對apk體積影響不大

缺點:

  • 需要下次啟動才會生效
  • 最大挑戰在於效能,即Dalvik平臺存在插樁導致的效能損耗,Art平臺由於地址偏移問題導致補丁包可能過大的問題
  • 虛擬機器在安裝期間為類打上CLASS_ISPREVERIFIED標誌是為了提高效能的,我們強制防止類被打上標誌是否會影響效能?這裡我們會做一下更加詳細的效能測試.但是在大專案中拆分dex的問題已經比較嚴重,很多類都沒有被打上這個標誌。

插樁方案效能上的痛點:

2018 深入解析Android熱修復技術

 

3.4 美團Robust — Instant Run 熱插拔原理

原理:

  • Robust外掛對每個產品程式碼的每個函式都在編譯打包階段自動的插入了一段程式碼,插入過程對業務開發是完全透明
  • 編譯打包階段自動為每個class都增加了一個型別為ChangeQuickRedirect的靜態成員,而在每個方法前都插入了使用changeQuickRedirect相關的邏輯,當 changeQuickRedirect不為null時,可能會執行到accessDispatch從而替換掉之前老的邏輯,達到fix的目的。

2018 深入解析Android熱修復技術

 

優點:

  • 幾乎不會影響效能(方法呼叫,冷啟動)
  • 支援Android2.3-8.x版本
  • 高相容性(Robust只是在正常的使用DexClassLoader)、高穩定性,修復成功率高達99.9%
  • 補丁實時生效,不需要重新啟動
  • 支援方法級別的修復,包括靜態方法
  • 支援增加方法和類
  • 支援ProGuard的混淆、內聯、優化等操作

缺點:

  • 程式碼是侵入式的,會在原有的類中加入相關程式碼
  • so和資源的替換暫時不支援
  • 會增大apk的體積,平均一個函式會比原來增加17.47個位元組,10萬個函式會增加1.67M。
  • 會增加少量方法數,使用了Robust外掛後,原來能被ProGuard內聯的函式不能被內聯了

3.5 微信Tinker

原理:

  • 服務端做dex差量,將差量包下發到客戶端,在ART模式的機型上本地跟原apk中的classes.dex做merge,merge成為一個新的merge.dex後將merge.dex插入pathClassLoader的dexElement,原理類同Q-Zone,為了實現差量包的最小化,Tinker自研了DexDiff/DexMerge演算法。Tinker還支援資源和So包的更新,So補丁包使用BsDiff來生成,資源補丁包直接使用檔案md5對比來生成,針對資源比較大的(預設大於100KB屬於大檔案)會使用BsDiff來對檔案生成差量補丁。

2018 深入解析Android熱修復技術

 

2018 深入解析Android熱修復技術

 


優點:

  • 支援動態下發程式碼
  • 支援替換So庫以及資源

缺點:

  • 不能即時生效,需要下次啟動

Tinker已知問題:

  • Tinker不支援修改AndroidManifest.xml,Tinker不支援新增四大元件(1.9.0支援新增非export的Activity);
  • 由於Google Play的開發者條款限制,不建議在GP渠道動態更新程式碼;
  • 在Android N上,補丁對應用啟動時間有輕微的影響;
  • 不支援部分三星android-21機型,載入補丁時會主動丟擲”TinkerRuntimeException:checkDexInstall failed”;
  • 對於資源替換,不支援修改remoteView。例如transition動畫,notification icon以及桌面圖示。

Tinker效能痛點:

  • Dex合併記憶體消耗在vm head上,容易OOM,最後導致合併失敗。
  • 如果本身app佔用記憶體已經比較高,可能容易導致app本系統殺掉。

3.6 阿里Sophix

原理(雙劍合璧):

2018 深入解析Android熱修復技術

 

優化Andfix(突破底層結構差異,解決穩定性問題):


Andfix底層ArtMethod結構時採用內部變數一一替換,倒是這個各個廠商是會修改的,所以相容性不好。

2018 深入解析Android熱修復技術

 

Sophix改變了一下思路,採用整體替換方法結構,忽略底層實現,從而解決相容穩定性問題。

2018 深入解析Android熱修復技術

 

突破QQ和Tinker的缺陷


QQ和Tinker的缺陷

2018 深入解析Android熱修復技術

 

Sophix對dex的解決方案

  • Dalvik下采用阿里自研的全量dex方案:不是考慮把補丁包的dex插到所有dex前面(dex插樁),而是想辦法在原理的dex中刪除(只是刪除了類的定義)補丁dex中存在的類,這樣讓系統查詢類的時候在原來的dex中找不到,那麼只有補丁中的dex載入到系統中,系統自然就會從補丁包中找到對應的類。
  • Art下本質上虛擬機器以及支援多dex的載入,Sophix的做法僅僅是把補丁dex作為主dex(classes.dex)而已,相當於重新組織了所有的dex檔案:把補丁包的dex改名為classes.dex,以前apk的所有dex依次改為classes2.dex、classes3.dex … classesx.dex,如下圖所示。

2018 深入解析Android熱修復技術

 

資源修復另闢蹊徑


常用方案(Instant Run技術):這種方案的相容問題在於替換AssetManager的地方

2018 深入解析Android熱修復技術

 

Sophix資源修復方案

2018 深入解析Android熱修復技術

 

SO修復另闢蹊徑


2018 深入解析Android熱修復技術

 

四、Tinker框架解析

之所以只貼了Tinker的程式碼框架,是因為目前開源的方案中是最好的,當然除了Robust。

程式碼結構

2018 深入解析Android熱修復技術

 

修復流程

2018 深入解析Android熱修復技術

 

這裡後續再補一個詳細的原始碼分析,敬請期待

五、對比圖(來自不同的地方)

來自Tinker的對比

2018 深入解析Android熱修復技術

 

來自Sophix的對比

2018 深入解析Android熱修復技術

 

來自蘑菇街 Android 熱修復探索之路

2018 深入解析Android熱修復技術

 

2018 深入解析Android熱修復技術

 

六、總結

如果不考慮增大apk的體積,只是簡單的修復程式碼,不修復so和資源,選擇Robust是最穩定的,否則的話選擇Tinker是一個不錯的方案。雖然阿里Sophix橫空出世,但是它不開源,而且商業收費,所以一般不是很賺錢的app選擇收費的可能就很小了。不過它確實各方面都做了大量的優化,本文中的很多知識點也來源於阿里的《Android熱修復技術原理.pdf》一書,本書值得一讀,裡面就是基於Sophix框架來編排的。

歡迎大家加入Android高階開發QQ群;701740775,

本群提供免費的學習指導 架構資料 以及免費的解答

不懂得問題都可以在本群提出來 還會有職業生涯規劃以及面試指導

進群修改群備註:開發年限-地區-經驗

方便架構師解答問題


相關文章