1. 程式人生 > >Android熱補丁原理簡單分析與問題思考

Android熱補丁原理簡單分析與問題思考

Android熱補丁(熱修復)從2016年微信的Tinker開源後掀起了一個熱潮。時隔一年,阿里推出《深入探索android熱修復技術原理》技術書籍,在推廣其Sophix的同時非常詳細地描述了其方案的實現過程,以及遇到的各種坑,引來大家的關注與分析。可以看到大公司紛紛推出自己的熱補丁方案,大大小小的應用,都開始嘗試在現有產品中整合或修改使用。

面對熱補丁給人的美好願景,相信大多數開發、運維人員都會為之所動。我們的產品也期望加入這一功能,但是在一段時間的測試和方案分析後,發現理想很豐滿,現實卻很骨感。本文在簡單分析主流的熱補丁原理後,丟擲一些自己想到或遇到的問題作為思考點,供看到的人蔘考。

熱補丁概念

熱補丁,百科中定義為“熱補丁(hotfix),又稱為patch,指能夠修復軟體漏洞的一些程式碼,是一種快速、低成本修復產品軟體版本缺陷的方式。”,微信開發者定義為,“讓應用能夠在無需重新安裝的情況實現更新,幫助應用快速建立動態修復能力”。總的來說,在Android上的期望是,在無需打擾使用者手動安裝的情況下,實現應用的更新。

從字面理解來看,當應用出現嚴重問題需要立即修復,只需下發補丁包,即可快速將問題修復,既不打擾使用者,也可快速修復問題。然後各種減少崩潰率,提升使用者留存等等。再激進一些,直接引申為熱更新,快速升級應用,豈不是更美好。但你大致理解熱補丁的原理和限制後,再結合應用的實際情況,看看這些方案對你的實際意義。《微信Android熱補丁實踐演進之路》也給了很好的分析和說明。

分類對比

從目前看到的較大的幾個熱補丁方案的技術原理來看,大體可以分為兩類:
Java層:大部分僅在Java層修改,通過動態載入程式碼和資源來實現
Native層:在Java層做處理的同時,Native層做了大量改動來實現程式碼替換

先來看看我瞭解到的幾家方案,僅包含目前可用和自認為比較流行的(如有遺漏,歡迎補充)
Native層修改:
阿里百川Sophix:從AndFix發展而來,但做了大量修改和完善(可以說和AndFix基本不同)。基本包含了Java層動態載入的方案,同時具有底層替換方案,部分情況可在無需重啟動應用的情況下實現修復。定位在緊急修復線上問題和快速釋出新鮮功能。不過不開源,作為阿里百川的產品服務在提供。

Java層修改:
大體思想都是動態載入,區別在於Multidex中dex如何替換和載入,application類如何替換,so庫如何替換等細節上,也都借鑑了InstantRun的實現。

微信Tinker:重點放在效能上,大量精力集中在盡力減少補丁包體積,定位不只在緊急問題修復,同時認為可使用在A/B Test上
QQ空間QFix:主要就是熱修復,也沒有開源
美團Robust:重在補丁成功率高,實時修復緊急問題,暫時不支援資源和so的修復
餓了麼Amigo:定位支援熱更新,支援熱修復

借用阿里文章的對比圖:
熱補丁對比圖
由上圖可見,阿里的Sophix功能最強大,另外從其推出的原理解釋書籍也可知它最複雜,而且不開源,一旦出問題,我們就得相信阿里的服務態度(提工單處理伺服器的問題還是很快很好的)。Tinker的大量精力在效能上,如怎樣減少補丁包的體積,增加在本地合成Dex的成功率上。對於如何替換Application和so反而需要改動程式碼,不太友好。下面我從最簡單的Amigo的實現來看看熱修復在Java層修改的基本原理,同時穿插的說說微信Tinker上的一些不同之處。

原理分析

1.先從整體上簡單看Android應用安裝及執行過程:
(1)應用的apk包被安裝器呼叫,檢查應用簽名後,解析apk中的AndroidManifest,記錄許可權宣告和四大元件等資訊,解壓出lib中的so庫;
(2)桌面應用收到應用安裝資訊,解析apk獲得應用圖示顯示出來,並存儲啟動Activity資訊;
(3)當桌面點選該應用執行時,呼叫啟動Activity
(4)由系統啟動應用的程序,預設程序名是應用安裝時寫在AndroidManifest中的包名
(5)應用程序載入apk中dex裡的程式碼,載入必要的資源
(6)顯示啟動Activity頁面

2.熱補丁執行流程
熱補丁所做的改動都集中在應用程序啟動後,在載入程式碼和資源時做必要的替換,大體流程是引導類,檢查是否有必要升級,需要的話替換程式碼和資源。
(1)引導類Application
應用程序能控制的程式碼入口是Application,一般在attachBaseContext中和onCreate中處理。Amigo提供編譯外掛,在基本不改變現有程式碼的情況下,替換Application類為Amigo類,在attachBaseContext中校驗當前正在使用的版本,判斷是否需要升級,從新apk中解壓程式碼和so,最後再呼叫應用原Application;而Tinker也替換Application,但通過提供註解,生成類似的代理來實現,需要修改使用了自己Application類的程式碼。另外在Tinker中dex是補丁包,需要在獨立程序中重新合成新dex,之後才能使用。
(2)程式碼替換
在attachBaseContext中反射獲取LoadedApk,並替換mClassloader為AmigoClassLoader,繼承DexClassLoader,在建立時添加了新的dex,並指定了新so的路徑,覆寫了findResource,loadClass方法。
(3)資源替換
在attachBaseContext中反射獲取資源引用,建立新的AssetManager並替換。

最後,執行attachPatchedApplication,載入補丁apk中的Application,並在onCreate中將Amigo類替換。
需要說明的是這僅是Java層方案的大體流程。阿里Sophix在融合了Java層方案的同時還增加了Native層的實時替換

問題思考

現在來思考熱補丁的定位,是能動態修復問題,但能作為新應用不斷升級麼?
1.先看限制:
(1)不支援AndroidManifest的修改,新增元件、許可權成為問題;當然如果在裡面設定的各種圖示也被限制到舊的資原始檔上(Amigo支援增加元件)
(2)notification & widget中RemoteViews的自定義佈局不支援修改,只支援內容修復

2.再看問題
(1)版本維護問題:
當定位在熱補丁,僅修復緊急問題,之後很快升級到正式版,這樣不會打亂原有的發版計劃和流程,基本問題不大。但是定位成熱更新,頻繁熱修復升級,需要考慮補丁的版本,原版本的不同組合;隨著新版本和新補丁不斷髮布,維護交叉升級,可能會給測試人員和開發人員一定負擔;另外熱補丁的成功率不能做到100%,又涉及到版本回退的問題,當補丁多次後,還能正常回退麼,需要考慮。
(2)熱補丁包問題
Tinker主要精力放在如何縮小補丁包,而Amigo則是全包下發。因此不得不考慮補丁包的大小,以及對流量造成的影響;另外由於添加了proguard等需要保留部分資訊,也需要考慮;而原應用有動態載入的,也得考慮相關策略;對於多渠道包,定製版本等,就需要額外考慮
(3)升級控制權問題
個人應用升級控制權都在自己手中,而企業使用者,應用的升級都有客戶參與,這種熱補丁的修復又多了一個去考慮的方面

文章最後,補充下自己選擇Amigo的原因:
(1)雖然Amigo需要下發完整apk,增加了補丁包體積,但是不需要額外維護版本,保持正常的發版流程即可;
(2)對Application的修改比較簡單,不像Tinker那樣無法使用原有的自定義Application類
(3)支援透明的so替換,Tinker需要修改程式碼
(4)不用擔心proguard,保留R.txt等
(5)話說Sophix都滿足,但是不開源啊

相關推薦

Android補丁原理簡單分析問題思考

Android熱補丁(熱修復)從2016年微信的Tinker開源後掀起了一個熱潮。時隔一年,阿里推出《深入探索android熱修復技術原理》技術書籍,在推廣其Sophix的同時非常詳細地描述了其方案的實現過程,以及遇到的各種坑,引來大家的關注與分析。可以看到大公

CVE-2018-7600 Drupal漏洞原理簡單分析復現

0x00元件背景 Drupal是使用PHP語言編寫的開源內容管理框架(CMF),它由內容管理系統(CMS)和PHP開發框架(Framework)共同構成。連續多年榮獲全球最佳CMS大獎,是基於PHP語言最著名的WEB應用程式。 0x01漏洞位置 這裡有個call_user_func

Android補丁技術—dexposed原理簡析(阿里Hao)

本文由嵌入式企鵝圈原創團隊成員、阿里資深工程師Hao分享。上篇文章《Android無線開發的幾種常用技術》我們介紹了幾種android移動應用開發中的常用技術,其中的熱補丁正在被越來越多的開發團隊所使用

Android ListView itemType使用Holder原理簡單分析

之前寫過一篇關於Holder複用原理的文章《Android ListView使用Holder優化原理》,此篇著重分析RecycleBin資料結構 原始碼在AbsListView中,RecycleBin一共有兩個儲存結構分別是ActiveViews 和 ScrapVie

Android 修復原理,DVM或ARTJVM的介紹ClassLoad及雙親委派模型理解

導語 熱修復說白了就是”打補丁”,通過事先設定的介面從網上下載無Bug的程式碼來替換有Bug的程式碼。這樣就省事多了,使用者體驗也好。這樣帶來的優勢就是成本低、效率高。熱修復的特點:無需重新發版,實時高效熱修復;使用者無感知修復,無需下載新的應用,代價小;修復成功率

Android 補丁動態修復框架小結

clas detail tle androi bsp blog .net details class Android 熱補丁動態修復框架小結Android 熱補丁動態修復框架小結

Android-貪吃蛇小遊戲-分析實現-Kotlin語言描述

otl bject vid oid 小遊戲 同時 們的 http 畫布 Android-貪吃蛇小遊戲-分析與實現-Kotlin語言描述 Overview 本章的主要的內容是貪吃蛇小遊戲的分析和實現,關於實現的具體代碼可以在,文章底部的github的鏈接中找到。 整個遊戲通過

核心補丁原理介紹、製作、使用、驗證方法

此文已由作者楊延亮授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。 簡介 核心熱補丁是一種無需重啟作業系統,動態為核心打補丁的技術。系統管理員基於該技術,可以在不重啟系統的情況下,修復核心BUG或安全漏洞,可以在最大程度上減少系統宕機時間,增加系統的可用性。

redis原始碼分析思考(十九)——AOF持久化

    為了解決持久化檔案很龐大以及會阻塞伺服器的 情況,redis提出一種新的持久化方案:AOF持久化。AOF持久化是redis儲存資料的另外一種方式,全稱Append Only File,與RDB持久化不同的是,AOF持久化是隻儲存從客戶端鍵入

redis原始碼分析思考(十八)——RDB持久化

    redis是一個鍵值對的資料庫伺服器,伺服器中包含著若干個非空的資料庫,每個非空資料庫裡又包含著若干個鍵值對。因為redis是一個基於記憶體存貯的資料庫,他將自己所存的資料存於記憶體中,如果不將這些資料及時的儲存在硬碟中,當電腦關機或者進行

redis原始碼分析思考(十七)——有序集合型別的命令實現(t_zset.c)

    有序集合是集合的延伸,它儲存著集合元素的不可重複性,但不同的是,它是有序的,它利用每一個元素的分數來作為有序集合的排序依據,現在列出有序集合的命令: 有序集合命令 命令 對應操作 時

redis原始碼分析思考(十六)——集合型別的命令實現(t_set.c)

    集合型別是用來儲存多個字串的,與列表型別不一樣,集合中不允許有重複的元素,也不能以索引的方式來通過下標獲取值,集合中的元素還是無序的。在普通的集合上增刪查改外,集合型別還實現了多個集合的取交集、並集、差集,集合的命令如下表所示: 集合命

redis原始碼分析思考(十五)——雜湊型別的命令實現(t_hash.c)

    雜湊型別又叫做字典,在redis中,雜湊型別本身是一個鍵值對,而雜湊型別裡面也存貯著鍵值對,其對應關係是,每個雜湊型別的值對應著一個鍵值對或多對鍵值對,如圖所示: 雜湊型別命令 命令 對應操

redis原始碼分析思考(十四)——列表型別的命令實現(t_list.c)

    列表型別是用來存貯多個字串物件的結構。一個列表可以存貯232-1個元素,可以對列表兩端進行插入(push)、彈出(pop),還可以獲取指定範圍內的元素列表、獲取指定索引的元素等等,它可以靈活的充當棧和佇列的角色。下面列出列表的命令: 列

redis原始碼分析思考(十三)——字串型別的命令實現(t_string.c)

    在對字串操作的命令中,主要有增加刪查該、批處理操作以及編碼的轉換命令,現在列出對字串物件操作的主要常用命令: 常用命令表 命令 對應操作 時間複雜度

DWM1000 測距原理簡單分析

DWM1000 超寬頻測距,使用的TOF(time of fly) 的方式,也就是計算無線電磁波傳輸時間,通過傳輸的時間換算成距離。 電磁波傳輸速率和光速一樣,速度是299792.458km/s,可參見百度百科。如果想通過測試這個傳播時間換算距離,那麼就需要非常高的內部時鐘。然。。。並不是有了高速的內部時鐘即

Android修復原理簡述

本文為《2018夯實基礎》系列之熱修復原理簡述 作者:Bob 一、背景 ① 為什麼會出現熱修復技術? 大家都是開發,所以應該都知道有一個東西我們永遠也避免不了。不錯,**Bug!**我們在開發階段碰到bug那還好,直接解決就是了,大不了讓測試多測一輪。可是,如果

redis原始碼分析思考(三)——字典中鍵的兩種hash演算法

      在Redis字典中,得到鍵的hash值顯得尤為重要,因為這個不僅關乎到是否字典能做到負載均衡,以及在效能上優勢是否突出,一個良好的hash演算法在此時就能發揮出巨大的作用。而一個良好的has

redis原始碼分析思考(八)——物件

    談及物件,我們不免會立即聯想到Java、C++等面向物件的語言,而在C中是沒有物件這一說法的,為了方便管理與程式碼整體的優化,redis基於前面幾篇部落格的資料結構自建了一套物件系統。這個系統包含著字串物件、列表物件、雜湊物件、集合物件以及有序集合物件。

redis原始碼分析思考(十七)——有序集合型別的命令實現(t_set.c)

    有序集合是集合的延伸,它儲存著集合元素的不可重複性,但不同的是,它是有序的,它利用每一個元素的分數來作為有序集合的排序依據,現在列出有序集合的命令: 有序集合命令 命令 對應操作 時間複