1. 程式人生 > >阿里 Dexposed 熱修復原理

阿里 Dexposed 熱修復原理

前言

Andfix 算是熱修復方案中,native流派的典範了。在講解Andfix之前,我們首先了解一下Dexposed,Andfix 是在Dexposed的基礎上演進的。

Dexposed介紹

阿里手淘團隊基於 Xposed 研發出來的 AOP 框架,方法級粒度,可以進行 AOP 程式設計、插樁、熱補丁、SDK hook 等功能。它的熱補丁方案原理圖大致如下::
dexposed.png

從上圖中我們可以看出,它的主要原理是將 Java method 改變為 native, 並且將這個方法的實現連結到一個通用的 Native Dispatch 方法(即一個公共分發函式上)來修改方法載入邏輯以實現熱補丁功能。
和 Xposed 不同的是,Xposed 通過劫持 zygote(須 root ),而 Dexposed 則是通過劫持 Java method (而非劫持 class loader)。我們可以用它來熱替換某個導致崩潰的方法,此外手淘還用它作效能監控。這主要得益於無侵入式的方法呼叫 Befor 和 After 事件,能夠讓我們很好的記錄和分析一個方法的呼叫時間。開源專案 promeG/XLog 就是基於 dexposed 實現的方法呼叫 logging。
但是它有個硬傷:不支援 art 平臺。因此在Android L推出後,2015年起它就逐漸淡出了廣大開發者的視線了。不過它的思想還是值得我們借鑑的。

AOP介紹

AOP(Aspect Oriented Programming),也就是面向方面程式設計,是通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。利用 AOP 可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
AOP一般應用在日誌記錄,效能統計,安全控制,事務處理,異常處理等方面,它的主要意圖是將日誌記錄,效能統計,安全控制,事務處理,異常處理等程式碼從業務邏輯程式碼中劃分出來,通過對這些行為的分離,我們希望可以將它們獨立到非業務邏輯的方法中,進而改變這些行為的時候不影響業務邏輯的程式碼。

Dexposed 示例

我們可以利用 Dexposed 在應用中所有的 Activity.onCreate(Bundle) 函式呼叫之前和之後增加一些處理:

dexposedsample.png

從程式碼我們可以看到入口是DexposedBridge.findAndHookMethod方法,詳情細節就不過多闡述了,有興趣的同學可以自行閱讀dexposed的開源專案原始碼,GitHub地址是:https://github.com/alibaba/dexposed

這裡給出大致流程:
1. 呼叫DexposedBridge.findAndHookMethod,進入到DexposedBridge類(Java層邏輯)
2. 通過XposedHelpers.findMethodExact找到要hook的java方法,然後再用hookMethod進行真正的hook。
3. hookMethod方法先把hook成功後的callback、要hook的方法的引數和返回值型別儲存到AdditionalHookInfo中,把它作為引數傳給hookMethodNative。hookMethodNative是一個native方法,它的第3個引數slot表示該Method在class的方法表中所處的位置,在native的實現中會用到這個slot。
4. hookMethod 方法中呼叫hookMethodNative,執行Native層方法。
6. com_taobao_android_dexposed_DexposedBridge_hookMethodNative (JNI入口),把Java層傳遞的資訊構造成DexposedInfo資訊,然後設定hook方法accessFlags設定為ACC_NATIVE ,即native方法,並且指定nativeFunc函式 ( 為什麼會這麼做:

method的結構體表示了一個Java層函式, 而其中的accessFlags屬性如果是ACC_NATIVE , 則dvm在呼叫原Java函式的時候, 會轉向呼叫屬性nativeFunc 所指向的函式)。
7. native層用dvm的各種函式來操作Method的指標和物件來控制函式,最後通過反射呼叫handleHookedMethod回到Java層的方法handleHookedMethod,回到Java世界。

下一篇是 Andfix 方案原理分析篇,後續整理好會發出來。