Android熱更新實現原理
原文出處:http://blog.csdn.net/lzyzsd/article/details/49843581
最近Android社群的氛圍很不錯嘛,連續放出一系列的Android動態載入外掛和熱更新庫,這篇文章就來介紹一下Android中實現熱更新的原理。
ClassLoader
我們知道Java在執行時載入對應的類是通過ClassLoader來實現的,ClassLoader本身是一個抽象來,Android中使用PathClassLoader類作為Android的預設的類載入器,
PathClassLoader其實實現的就是簡單的從檔案系統中載入類檔案。PathClassLoade本身繼承自BaseDexClassLoader,BaseDexClassLoader重寫了findClass方法,
該方法是ClassLoader的核心
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
- Class c = pathList.findClass(name, suppressedExceptions);
- if (c == null) {
- ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
- for (Throwable t : suppressedExceptions) {
- cnfe.addSuppressed(t);
- }
- throw cnfe;
- }
- return c;
- }
看原始碼可知,BaseDexClassLoader將findClass方法委託給了pathList物件的findClass方法,pathList物件是在BaseDexClassLoader的建構函式中new出來的,
它的型別是DexPathList。看下DexPathList.findClass原始碼是如何做的:
- public Class findClass(String name, List<Throwable> suppressed) {
- for (Element element : dexElements) {
- DexFile dex = element.dexFile;
- if (dex != null) {
- Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
- if (clazz != null) {
- return clazz;
- }
- }
- }
- if (dexElementsSuppressedExceptions != null) {
- suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
- }
- return null;
- }
直接就是遍歷dexElements列表,然後通過呼叫element.dexFile物件上的loadClassBinaryName方法來載入類,如果返回值不是null,就表示載入類成功,會將這個Class物件返回。
而dexElements物件是在DexPathList類的建構函式中完成初始化的。
- this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory, suppressedExceptions);
makeDexElements所做的事情就是遍歷我們傳遞來的dexPath,然後一次載入每個dex檔案。
實現
上面分析了Android中的類的載入的流程,可以看出來DexPathList物件中的dexElements列表是類載入的一個核心,一個類如果能被成功載入,那麼它的dex一定
會出現在dexElements所對應的dex檔案中,並且dexElements中出現的順序也很重要,在dexElements前面出現的dex會被優先載入,一旦Class被載入成功,
就會立即返回,也就是說,我們的如果想做hotpatch,一定要保證我們的hotpacth dex檔案出現在dexElements列表的前面。
要實現熱更新,就需要我們在執行時去更改PathClassLoader.pathList.dexElements,由於這些屬性都是private的,因此需要通過反射來修改。另外,構造我們自己的dex檔案
所對應的dexElements陣列的時候,我們也可以採取一個比較取巧的方式,就是通過構造一個DexClassLoader物件來載入我們的dex檔案,並且呼叫一次dexClassLoader.loadClass(dummyClassName);
方法,這樣,dexClassLoader.pathList.dexElements中,就會包含我們的dex,通過把dexClassLoader.pathList.dexElements插入到系統預設的classLoader.pathList.dexElements列表前面,就可以讓系統優先載入我們的dex中的類,從而可以實現熱更新了。下面展示一部分程式碼
- private static synchronized Boolean injectAboveEqualApiLevel14(
- String dexPath, String defaultDexOptPath, String nativeLibPath, String dummyClassName) {
- Log.i(TAG, "--> injectAboveEqualApiLevel14");
- PathClassLoader pathClassLoader = (PathClassLoader) DexInjector.class.getClassLoader();
- DexClassLoader dexClassLoader = new DexClassLoader(dexPath, defaultDexOptPath, nativeLibPath, pathClassLoader);
- try {
- dexClassLoader.loadClass(dummyClassName);
- Object dexElements = combineArray(
- getDexElements(getPathList(pathClassLoader)),
- getDexElements(getPathList(dexClassLoader)));
- Object pathList = getPathList(pathClassLoader);
- setField(pathList, pathList.getClass(), "dexElements", dexElements);
- } catch (Throwable e) {
- e.printStackTrace();
- return false;
- }
- Log.i(TAG, "<-- injectAboveEqualApiLevel14 End.");
- return true;
- }
完整的demo請參考我的GitHub
上面只是說了一下hotpatch的原理,具體實現的時候,如果你的app應用了multidex,還會遇到其他的坑,請參考:
相關文章
- Android熱更新實現方式Android
- ElasticSearch IK熱詞自動熱更新原理與Golang實現ElasticsearchGolang
- Flutter Android 端熱修復(熱更新)實踐FlutterAndroid
- uniapp實現熱更新APP
- 從ClassLoader到Android外掛化以及熱更新原理Android
- webpack 熱更新原理Web
- Flutter 熱更新功能實現Flutter
- Android熱修復原理Android
- Android熱更新方案之阿里AndFix 原理以及原始碼解析Android阿里原始碼
- Android SharedPreferences 實現原理解析Android
- Android端Flutter熱更新,相容FlutterBoostAndroidFlutter
- Unity3D熱更新之LuaFramework篇[09]--資源熱更新與程式碼熱更新的具體實現Unity3DFramework
- Android動畫實現繪製原理Android動畫
- Android RollBack機制實現原理剖析Android
- 熱修復(一)原理與實現詳解
- Android進階5:SurfaceView實現原理分析AndroidView
- Notification之 – Android5.0實現原理(一)Android
- Unity3D熱更新之LuaFramework篇[08]--熱更新原理及熱更伺服器搭建Unity3DFramework伺服器
- konfig:採用ConfigMap實現線上配置熱更新
- Android-Handler訊息機制實現原理Android
- React Native 熱更新實踐React Native
- Android 騰訊Bugly熱更新接入(Kotlin語言)AndroidKotlin
- 說說Android動態換膚實現原理吧Android
- Laravel 中引入 Swoole Websocket 並實現熱更新 Reload 程式碼LaravelWeb
- 【Android 熱修復】美團Robust熱修復框架原理解析Android框架
- webpack與browser-sync熱更新原理深度講解Web
- 19. 從零開始編寫一個類nginx工具, 配置資料的熱更新原理及實現Nginx
- 基於vue-cli3 SSR 程式實現熱更新功能Vue
- 記 Arthas 實現一次 CPU 排查與程式碼熱更新
- 外掛化實現Android多主題功能原理剖析Android
- Vue2非同步批量更新與computed、watcher原理實現Vue非同步
- 筆記 深入探索Android熱修復技術原理筆記Android
- Android進階(八)熱修復基本原理Android
- 熱更新技術簡易原理及技術推薦
- 與Android熱更新方案Amigo的初次接觸AndroidGo
- 與Android熱更新方案Amigo的親密接觸AndroidGo
- Android自定義View實現流式佈局(熱門標籤效果)AndroidView
- uiapp套殼熱更新實現方案(h5也是uiapp寫的)UIAPPH5
- 關於WebRTC視訊Android端實現的原理解讀WebAndroid