#熱修復技術
---
APP提早發出去的包,如果出現客戶端的問題,實在是干著急,覆水難收。因此線上修復方案迫在眉睫。
###概述
基于Xposed中的思想,通過修改c層的Method實例描述,來實現更改與之對應的java方法的行為,從而達到修復的目的。
###Xposed
誕生于XDA論壇,類似一個應用平臺,不同的是其提供諸多系統級的應用。可實現許多神奇的功能。Xposed需要以越獄為前提,像是iOS中的cydia。
Xposed可以修改任何程序的任何java方法(需root),github上提供了XposedInstaller,是一個android app。提供很多framework層,應用層級的程序。開發者可以為其開發一些系統或應用方面的插件,自定義android系統,它甚至可以做動態權限管理(XposedMods)。
###Android系統啟動與應用啟動
Zygote進程是Android手機系統啟動后,常駐的一個名為‘受精卵’的進程。
* zygote的啟動實現腳本在/init.rc文件中
* 啟動過程中執行的二進制文件在/system/bin/app_process
任何應用程序啟動時,會從zygote進程fork出一個新的進程。并裝載一些必要的class,invoke一些初始化方法。這其中包括像:
* ActivityThread
* ServiceThread
* ApplicationPackageManager
等應用啟動中必要的類,觸發必要的方法,比如:handleBindApplication,將此進程與對應的應用綁定的初始化方法;同時,會將zygote進程中的dalvik虛擬機實例復制一份,因此每個應用程序進程都有自己的dalvik虛擬機實例;會將已有Java運行時加載到進程中;會注冊一些android核心類的jni方法到虛擬機中,支撐從c到java的啟動過程。
###Xposed做了手腳
Xposed在這個過程改寫了app_process(源碼在Xposed : a modified app_process binary),替換/system/bin/app_process這個二進制文件。然后做了兩個事:
1. 通過Xposed的hook技術,在上述過程中,對上面提到的那些加載的類的方法hook。
2. 加載XposedBridge.jar
這時hook必要的方法是為了方便開發者為它開發插件,加載XposedBridge.jar是為動態hook提供了基礎。在這個時候加載它意味著,所有的程序在啟動時,都可以加載這個jar(因為上面提到的fork過程)。結合hook技術,從而達到了控制所有程序的所有方法。
為獲得/system/bin/目錄的讀寫權限,因而需要以root為前提。
###Xposed的hook思想
那么Xposed是怎么hook java方法的呢?要從XposedBridge看起,重點在
XposedBridge.hookmethod(原方法的Member對象,含有新方法的XC_MethodHook對象);,這里會調到
```
private native synchronized static void hookMethodNative(Member method, Class<?> declaringClass, int slot, Object additionalInfo);
```
這個native的方法,通過這個方法,可以讓所hook的方法,轉向native層的一個c方法。如何做到?
```
When a transmit from java to native occurs, dvm sets up a native stack.
In dvmCallJNIMethod(), dvmPlatformInvoke is used to call the native method(signature in Method.insns).
```
在jni這個中間世界里,類型數據由jni表來溝通java和c的世界;方法由c++指針結合DVM*系(如dvmSlotToMethod,dvmDecodeIndirectRef等方法)的api方法,操作虛擬機,從而實現java方法與c方法的世界。
那么hook的過程是這樣:首先通過dexclassload來load所要hook的方法,分析類后,進c層,見代碼XposedBridge_hookMethodNative方法,拿到要hook的Method類,然后通過dvmslotTomethod方法獲取Method*指針,
```
Method* method = dvmSlotToMethod(declaredClass, slot);
```
declaredClass就是所hook方法所在的類,對應的jobject。slot是Method類中,描述此java對象在vm中的索引;那么通過這個方法,我們就獲取了c層的Method指針,通過
```
SET_METHOD_FLAG(method, ACC_NATIVE);
```
將該方法標記為一個native方法,然后通過
```
method->nativeFunc = &hookedMethodCallback;
```
定向c層方法到hookedMethodCallback,這樣當被hook的java方法執行時,就會調到c層的hookedMethodCallback方法。
通過meth->nativeFunc重定向MethodCallBridge到hookedMethodCallback這個方法上,控制這個c++指針是無視java的private的。
另外,在method結構體中有
```
method->insns = (const u2*) hookInfo;
```
用insns指向替換成為的方法,以便hookedMethodCallback可以獲取真正期望執行的java方法。
現在所有被hook的方法,都指向了hookedMethodCallbackc方法中,然后在此方法中實現調用替換成為的java方法。
###從Xposed提煉精髓
回顧Xposed,以root為必要條件,在app_process加載XposedBidge.jar,從而實現有hook所有應用的所有方法的能力;而后續動態hook應用內的方法,其實只是load了從zypote進程復制出來的運行時的這個XposedBidge.jar,然后hook而已。因此,若在一個應用范圍內的hook,root不是必須的,只是單純的加載hook的實現方法,即可修改本應用的方法。
業界內也不乏通過「修改BaseDexClassLoader中的pathList,來動態加載dex」方式實現熱修復。后者純java實現,但需要hack類的優化流程,將打CLASS_ISPREVERIFIED標簽的類,去除此標簽,以解決類與類引用不在一個dex中的異常問題。這會放棄dex optimize對啟動運行速度的優化。原則上,這對于方法數沒有大到需要multidex的應用,損失更明顯。而前者不觸犯原有的優化流程,只點殺需要hook的方法,更為純粹、有效。
- JavaSE(Java基礎)
- Java基礎知識
- Java中的內存泄漏
- String源碼分析
- Java集合結構
- ArrayList源碼剖析
- HashMap源碼剖析
- Hashtable簡介
- Vector源碼剖析
- LinkedHashMap簡介
- LinkedList簡介
- JVM(Java虛擬機)
- JVM基礎知識
- JVM類加載機制
- Java內存區域與內存溢出
- 垃圾回收算法
- Java并發(JavaConcurrent)
- Java并發基礎知識
- 生產者和消費者問題
- Thread和Runnable實現多線程的區別
- 線程中斷
- 守護線程與阻塞線程的情況
- Synchronized
- 多線程環境中安全使用集合API
- 實現內存可見的兩種方法比較:加鎖和volatile變量
- 死鎖
- 可重入內置鎖
- 使用wait/notify/notifyAll實現線程間通信
- NIO
- 數據結構(DataStructure)
- 數組
- 棧和隊列
- Algorithm(算法)
- 排序
- 選擇排序
- 冒泡排序
- 快速排序
- 歸并排序
- 查找
- 順序查找
- 折半查找
- Network(網絡)
- TCP/UDP
- HTTP
- Socket
- OperatingSystem(操作系統)
- Linux系統的IPC
- android中常用設計模式
- 面向對象六大原則
- 單例模式
- Builder模式
- 原型模式
- 簡單工廠
- 策略模式
- 責任鏈模式
- 觀察者模式
- 代理模式
- 適配器模式
- 外觀模式
- Android(安卓面試點)
- Android基礎知識
- Android內存泄漏總結
- Handler內存泄漏分析及解決
- Android性能優化
- ListView詳解
- RecyclerView和ListView的異同
- AsyncTask源碼分析
- 插件化技術
- 自定義控件
- ANR問題
- Art和Dalvik的區別
- Android關于OOM的解決方案
- Fragment
- SurfaceView
- Android幾種進程
- APP啟動過程
- 圖片三級緩存
- Bitmap的分析與使用
- 熱修復的原理
- AIDL
- Binder機制
- Zygote和System進程的啟動過程
- Android中的MVC,MVP和MVVM
- MVP
- Android開機過程
- EventBus用法詳解
- 查漏補缺
- Git操作