熱修復概念
當應用出現bug的時候,可以幫助我們在不進行重新安裝應用的情況下實現對bug的修復的能力
熱修復流程步驟
常見熱修復解決方案
可以注意到Tinker和QZone 是通過類替換的方式來實現熱修復,而AndFix和Robust不是通過類替換的方式來實現的;
另外通過類替換的方式來實現熱修復的兩個框架Tinker和QZone,是不能即時生效的,必須重啓後生效
類替換方案
Qzone
原理:基於Multidex分包方案,將解決後的類打進一個單獨的dex補丁包,放入Elements數組的最前面,當ClassLoader查找類的時候,會按照順序遍歷Elements數組,理論上如果在不同dex中有相同的類,ClassLoader會優選選擇排在前面的dex文件中的類。
差分算法+類替換方案
Tinker
原理:運行的時候,啓動一個新進程(耗時),通過dexdiff算法計算對比bug.apk和fix.apk中dex的區別生成fix.dex補丁包,在運行時將bug.apk的dex與補丁包合成,重啓後通過ClassLoader加載合成後的dex,完成修復
native hook方案
AndFix
原理:在native層動態替換java層的方法,在native層將方法的成員一個一個的替換,由於是在動態的替換方法,所以不需要重啓,是即時生效的
缺點:
需要針對dalvik虛擬機和art虛擬機做適配,需要考慮指令集的兼容問題,需要native代碼支持,兼容性上會有一定的影響
查看下圖源碼片段,源碼中將方法中有bug的成員替換成了fix之後的成員,而且針對dllvik虛擬機和art虛擬機做了適配
Sophix
原理:在native層利用memcpy(des,src,sizeof(ArtMethod))直接替換有bug的方法,不用關心artMethod的具體實現,所以解決了兼容性問題。
字節碼插樁方案
Robust
原理:利用字節碼插樁,對每個函數在編譯打包階段自動插入了一段代碼,類似於代理,將方法執行的代碼重定向到其它方法中
流程:
public static ChangeQuickRedirect changeQuickRedirect;
//有問題的代碼
@Modify //改動代碼後手動添加註解用於補丁包的生成
public long getIndex() {
return 100;
}
//經過插樁後實際執行的代碼
public long getIndex {
if(changeQuickRedirect != null) {
return 修復後的代碼;
}
return 100;
}
Robust爲每個class增加了個類型爲ChangeQuickRedirect的靜態成員,而在每個方法前都插入了使用changeQuickRedirect相關的邏輯,當 changeQuickRedirect不爲null時,可能會執行到accessDispatch從而替換掉之前老的邏輯,達到即時fix的目的。
總結
1.Tinker和QZone都是利用類替換的修復方式,區別是Tinker是利用差分算法生成記錄有修復前和修復後差分信息的dex,QZone是修復後的完整dex,一定程度上查分信息dex的大小是優於完整dex的。二者都是重啓後生效;
2.AndFix native層進行成員的替換,兼容性較差,已經不維護了,能即時生效
3.Robust 利用字節碼插樁,對每個函數在編譯打包階段自動插入了一段代碼,類似於代理;能即時生效