熱更新
1. 什麼是熱更新
對於“熱”這個字從不同的角度會有不同的觀點:
- 站在app開發者角度的“熱”是指在不發版的情況來實現更新。
- 從Google提出的“熱”是指值無需重新啓動。
熱更新就是不停機實時更新,HotUpdateHotFix,真正的熱更新是不用重啓就能更新,在Android 中還不能達到完全的真正熱更新。
在熱更新出現之前,通過反射註解、反射調用和反射注入等方式已經可以實現類的動態加載了。熱更新的實質就是替換,需要替換運行時新的類和資源文件的加載,就可以認爲是熱操作了。熱更新就是一種熱操作,它是一種改變app運行行爲的技術,其本質就是利用hook操作進行替換,在代碼上是一種侵入性的操作。
google和蘋果是不支持熱更新的,只有在中國特殊國情下才出現了這種黑科技,主要是熱更新對程序安全性有一定影響。
2. 爲什麼需要熱更新?
改善用戶體驗(節省流量、時間、操作程度),快速緊急修復Bug.修復立即生效,是熱修復所追求的宗旨。
3. 主流熱更新方案?
首先我們需要認知沒有完美的熱更新方案,只有更好的熱更新,熱更新不會有100%的成功率。截止2020上半年最強大的熱更新方案,我推薦使用Sophix。
熱修復因爲大量涉及android底層知識,又因爲android本身開源,華爲vivo小米幾大廠商都可能修改底層相關代碼,兼容困難。所以熱修復技術開發維護難度巨大,人力和時間投入不菲。目前主要有騰訊,阿里等幾家互聯網大廠因自身剛性需求,實現此功能。
熱更新的技術方案我將其分爲3種:
- 騰訊系的熱更新方案Tinker、Qzone。Tinker是騰訊系產品中熱更新的主力技術。
- 阿里系的熱更新技術,Andfix、阿里百川Hotfix1.X、Sophix。我們可以按順序看作是技術方法的逐步升級。Sophix在技術層結合了Tinker和HotFix,吸取了兩者之精華和優勢,個人認爲截止2020.05是目前最簡單實用及穩定強大的熱更新技術。
- 其他廠的熱更新方案如美團點評Robust、餓了麼 Amigo
4. 熱更新的兩條常規技術路線
- 類加載替換
對於類加載在熱更新中的使用,請查看我的另一篇博客《熱更新之Tinker類加載原理》 - 底層替換
底層替換是一種nativite方案,其操作是在Native修改Filed指針的方式,實現方法的替換,達到即時生效無需重啓,對應用無性能消耗的目的。
在類被加載後,類中的每個方法都會在虛擬機中對應ArtMethod,Artmethod記錄了這個java方法的所屬類、訪問權限、代碼執行內存地址等信息。通過在運行時利用hook操作native指針,通過這種篡改ArtMethod指針的方式,將補丁方法ArtMethod的成員值逐一賦給舊方法實現替換。所以該種方案能及時生效。
Native修改Filed指針需要在native層進行三步操作:
- 打開鏈接庫獲得操作句柄,獲得native層的內部函數,得到ClassObject對象
- 修改訪問權限屬性爲public
- 得到新舊方法的指針,新方法指向目標方法,實現方法的替換。
5.QZone熱更新
Qzone也是採用的類加載的方案,它修復後是單獨放在一個.dex中,插入到dexElements數組的最前面,讓虛擬機去加載修復完後的方法。
這樣的熱修復有一個大問題就是CLASS_ISPREVERIFIED
當兩個調用關係的類不在同一個DEX時,就會產生異常報錯。在APK安裝時,虛擬機需要將classes.dex優化成odex文件,然後纔會執行。
在這個過程中,會進行類的verify操作,如果調用關係的類都在同一個DEX中的話就會被打上CLASS_ISPREVERIFIED的標誌,然後纔會寫入odex文件。
6.Tinker熱更新
Tinker熱更新方案使用的是基於multidex原理的類加載方法,其詳細原理請閱讀《熱更新之Tinker類加載原理》
Tinker針對Qzone的不足,不再將patch.dex增加到elements數組中,而是差量的方式給出patch.dex,然後將patch.dex與應用的classes.dex合併,然後整體替換掉舊的DEX文件,以達到修復的目的。
優點:
1.合成整包,不用在構造函數插入代碼,防止verify。verify和opt在編譯期間就已經完成,不會在運行期間進行
2.性能提高。兼容性和穩定性比較高。
3.Tinker補丁的生成是通過Gradle插件來實現的,打包過程對開發者透明,不需要對包進行額外處理。
不足:
1.與Qzone補丁技術一樣,不支持即時生效,必須通過重啓應用的方式才能生效(如果是軟件啓動後才發佈的補丁,需要重啓兩次)。採用了ClassLoader機制
2.需要給應用開啓新的進程才能進行合併,並且很容易因爲內存消耗等原因合併失敗。
3.合併時佔用額外磁盤空間,對於多DEX的應用來說,如果修改了多個DEX文件,就需要下發多個patch.dex與對應的classes.dex進行合併操作時這種情況會更嚴重,因此合併過程的失敗率也會更高。
4. Tinker的接入侵入性太高了,打包也麻煩費時間。
7. Andfix熱更新
andfix採用的方法替換的熱更新方案,其熱更新流程。
Andfix的ArtMethod方法結構是根據Android開源代碼寫死的,面對國內廠商的定製,經常會導致兩者ArtMethod方法結構不一致,這也是兼容問題產生的根本原因。
Andfix優點:
- BUG修復的即時性,對應用無侵入,幾乎無性能損耗
- 補丁包同樣採用差量技術,生成的PATCH體積小
不足:
- 不支持新增字段,以及修改方法,也不支持對資源的替換。
- 由於廠商的自定義ROM,對少數機型暫不支持。
8.Sophix熱更新
Sophix是阿里雲提供的全平臺App熱修復服務方案。產品基於阿里巴巴首創hotpatch技術,提供最細粒度熱修復能力,讓您無需等待實時修復應用線上問題。
Sophix熱更新的實質有兩種更新方案:底層方法替換+類加載替換。它的補丁包是一種.jar格式。
爲了解決Andfix存在的底層替換兼容性問題,Sophix做了一些額外的優化。Sophix通過動態測試ArtMethod的Size(通過c層的mempy(dest、src、size)方法),進行全量拷貝。只要對當前虛擬機中的ArtMethod進行統一拷貝,完成替換就能消除不同虛擬機的導致的Artmethod結構差異。
優點:
- Sophix具有底層替換的修改及時性和類加載方案的兼容性,Sophix吸收了百川Hotfix和Tinker的優點於一生,會自動判斷在打補丁時選用哪種方案。
- Sophix採用非侵入式接入與打包,接入成本低,圖形化補丁生成,”傻瓜式接入”。
- 阿里提過了補丁管理平臺,無需開發者自己在服務器中開發管理功能。
- 部分更新無需重啓軟件,下載的patch極小,相比其他方案,通過兩種更新方案,修復成功率極高。
熱更新使用體會
我只使用過基於Bugly的Tinker和阿里的Sophix兩種熱更新方案。強烈推薦使用Sophix。爲什麼不推薦使用Bugly呢,雖然是免費的。
- Bugly的熱更新免費意味着服務質量差,技術QQ支持羣百年無響應,別指望能有技術人員來個你答疑。Sophix使用的是釘釘羣進行技術支持,技術支持響應速度和態度簡直天壤之別。
- 服務器時不時就會有崩潰問題,全量更新,熱更新不敢使用了,這服務器宕機實在有損大廠威嚴
- 針對同一版本,Bugly集成的Tinker只能打一次補丁,第二次就失敗了。Sophix可以對同一版本進行多次補丁修復
- Tinker的接入和打包都比較麻煩,代碼侵入性高。Sophix接入簡單,傻瓜式打包。
額外說明:
阿里有一整套的技術開發生態鏈,我可以服務器、後臺、數據庫、移動端測試、推送等都接入阿里雲。
其他鏈接: