日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android 热修复】热修复原理 ( 合并两个 Element[] dexElements | 自定义 Application 加载 Dex 设置 | 源码资源 )

發布時間:2025/6/17 Android 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 热修复】热修复原理 ( 合并两个 Element[] dexElements | 自定义 Application 加载 Dex 设置 | 源码资源 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、合并兩個 Element[] dexElements
  • 二、 完整修復包加載工具類
  • 三、 源碼資源





一、合并兩個 Element[] dexElements



在 【Android 熱修復】熱修復原理 ( 加載 Dex 文件到內存中 | DexClassLoader | PathClassLoader | 反射 Element[] dexElements ) 博客中已經將 系統加載的 Dex 文件對應的 Element[] dexElements 通過 PathClassLoader 類加載器獲取到了 , 同時修復包對應 Dex 文件 Element[] dexElements 通過 DexClassLoader 類加載器獲取到了 ;

下面開始將修復包對應的 Element[] dexElements 合并到系統 PathClassLoader 中的 Element[] dexElements 數組中 ;


在 【Android 熱修復】熱修復原理 ( 加載 Dex 文件到內存中 | DexClassLoader | PathClassLoader | 反射 Element[] dexElements ) 博客中

將系統 PathClassLoader pathClassLoader 的 DexPathList pathList 對象的 Element[] dexElements 成員systemDexElementsObject

自己在程序中的 DexClassLoader dexClassLoader 的 DexPathList pathList 對象的 Element[] dexElements 成員myDexElementsObject

進行融合 , 將 myDexElementsObject 插入到 systemDexElementsObject ;


首先要獲取 Dex 數組 , 但是 Element 類型無法引用 , 不是公開的 ;

先獲取 Element 類型 , 調用對象的 .getClass().getComponentType() 獲取 ;

// 獲取 Dex 數組 , Element 類型無法引用 , 不是公開的 // 首先獲取 Element 類型 // systemDexElementsObject Class<?> elementClass = systemDexElementsObject.getClass().getComponentType();

獲取兩個 Element[] dexElements 數組的成員個數 ;

// 獲取兩個 Element[] dexElements 數組的成員個數 // 系統中的 PathClassLoader 中的 Element[] dexElements 數組大小 int systemDexCount = Array.getLength(systemDexElementsObject); // 本應用中的 DexClassLoader 中的 Element[] dexElements 數組大小 int myDexCount = Array.getLength(myDexElementsObject);

使用 Array.newInstance 重新創建一個數組, 數組的長度是兩個數組之和 ;

// 重新創建一個數組 // 類型 : Class<?> elementClass // 長度 : systemDexCount + myDexCount Object elementArray =Array.newInstance(elementClass, systemDexCount + myDexCount);

填充創建的數組 , 這里特別注意 , 數組中的元素的順序很重要 , 一定要先放置修復包中的數組元素 , 然后放置應用自帶的 Dex 數組內容 , 這個順序一定不能亂 ;

// 填充數組內容, 這里特別注意 , 數組中的元素的順序很重要 , // 同樣類型的類 , 在多個 Dex 都存在 , 如果在前面的 Dex 中查找到了 , 就不再向后查找了 // 修復包的 Dex 要放在最前面 , 這樣才能起到修復作用// 先放置修復包 Dex for(int i = 0; i < myDexCount; i ++){// 獲取 myDexElementsObject 數組中的第 i 個元素// 放置到 elementArray 數組中的第 i 個元素位置Array.set(elementArray, i,Array.get(myDexElementsObject, i)); }// 再放置系統 Dex for(int i = 0; i < systemDexCount; i ++){// 獲取 systemDexElementsObject 數組中的第 i 個元素// 放置到 elementArray 數組中的第 i + myDexCount 個元素位置Array.set(elementArray,i + myDexCount,Array.get(systemDexElementsObject, i)); }

最后 , 通過反射方法 , 將合并后的 elementArray 數組放置到 PathClassLoader 中的 Element[] dexElements 中 ;

// 通過反射方法 // 將合并后的 elementArray 數組放置到 // PathClassLoader 中的 Element[] dexElements 中 systemDexElementsField.set(systemPathListObject, elementArray);

注意 : 此時熱修復還不能生效 , 需要進一步進行分包操作才可以 ;





二、 完整修復包加載工具類



package kim.hsl.hotfix;import android.content.Context; import android.util.Log;import java.io.File; import java.lang.reflect.Array; import java.lang.reflect.Field;import dalvik.system.DexClassLoader; import dalvik.system.PathClassLoader;public class FixDexUtils {/*** 加載 Dex 文件* @param context*/public static void loadDex(Context context){// 修復包可能有多個, 如先后進行了多次修復 , 存在多個修復包 Dex 文件// 這些 Dex 文件按照時間順序進行放置// 之前已經將 SD 卡中的 /storage/emulated/0/update.dex 文件拷貝到了// 原應用內置存儲空間 /data/user/0/kim.hsl.hotfix/app_odex/update.dex// /data/user/0/kim.hsl.hotfix/app_odex/ 目錄文件File filesDir = context.getDir("odex", Context.MODE_PRIVATE);// 獲取 /data/user/0/kim.hsl.hotfix/app_odex/ 目錄下的所有文件File[] listFiles = filesDir.listFiles();// 緩存 odex 文件的目錄 , 將 dex 優化為 odex 文件String optimizedDir = filesDir.getAbsolutePath() + File.separator + "cache_odex";// 過濾文件, 系統打包都是 classes.dex , classes1.dex , classes2.dex 等文件// 上傳的更新包 update.dex 以 .dex 為結尾// 以上面兩個條件作為過濾的依據for (File file : listFiles){if (file.getAbsolutePath().startsWith("classes") ||file.getAbsolutePath().endsWith(".dex")){// 將 dex 文件加載到內存中// 該 DexClassLoader 是 BaseDexClassLoader 的子類// BaseDexClassLoader 中有 DexPathList pathList 成員// 構造該類時 , 會自動將 dex 文件進行優化為 odex , 然后加載到上述 DexPathList pathList 中//// 參數一 : Dex 文件路徑// 參數二 : 緩存路徑, 指的是緩存 Odex 文件的目錄// 參數三 : Dex 中的 lib 庫路徑, 可以設置 null// 參數四 : 上下文的 ClassLoaderDexClassLoader dexClassLoader = new DexClassLoader(file.getAbsolutePath(),optimizedDir,null,context.getClassLoader());// 該 PathClassLoader 是用于加載查找 Android 應用所有 dex 文件的類加載器// 將上面獲取的 dexClassLoader 中的 DexPathList pathList// 插入到 PathClassLoader 中的 DexPathList pathList 成員中PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader();// BaseDexClassLoader 中的 DexPathList pathList 是 private 私有的// 無法直接獲取// 需要使用反射機制獲取該 Dex 數組// 拿到 PathClassLoader (繼承 BaseDexClassLoader 類) 對象后// 先使用反射機制獲取 private final DexPathList pathList 成員// 然后再次通過反射 , 獲取 DexPathList 中的 private final Element[] dexElements 成員try {// 加載系統的 Element[] dexElements ---------------------------------------------// 反射獲取 BaseDexClassLoader 類對象Class systemBaseDexClassLoaderClass =Class.forName("dalvik.system.BaseDexClassLoader");// 反射獲取 BaseDexClassLoader 中的 private final DexPathList pathList 字段Field systemPathListField =systemBaseDexClassLoaderClass.getDeclaredField("pathList");// 由于是私有成員字段 , 需要設置可訪問性systemPathListField.setAccessible(true);// 獲取系統的 PathClassLoader pathClassLoader 對象的// private final DexPathList pathList 成員Object systemPathListObject = systemPathListField.get(pathClassLoader);// 獲取 DexPathList 類Class systemPathListClass = systemPathListObject.getClass();// 獲取 DexPathList 類中的 private final Element[] dexElements 成員字段Field systemDexElementsField =systemPathListClass.getDeclaredField("dexElements");// 由于是私有成員字段 , 需要設置可訪問性systemDexElementsField.setAccessible(true);// 獲取 DexPathList pathList 對象的 Element[] dexElements 成員Object systemDexElementsObject =systemDexElementsField.get(systemPathListObject);// 系統的 Element[] dexElements 加載完畢-----------------------------------------// 上述反射的是系統的 PathClassLoader 的對象// 下面開始反射在本次循環方法中加載的 DexClassLoader dexClassLoader// 加載自己的 Element[] dexElements ---------------------------------------------// 反射獲取 BaseDexClassLoader 類對象Class myBaseDexClassLoaderClass =Class.forName("dalvik.system.BaseDexClassLoader");// 反射獲取 BaseDexClassLoader 中的 private final DexPathList pathList 字段Field myPathListField =myBaseDexClassLoaderClass.getDeclaredField("pathList");// 由于是私有成員字段 , 需要設置可訪問性myPathListField.setAccessible(true);// 獲取系統的 PathClassLoader pathClassLoader 對象的// private final DexPathList pathList 成員Object myPathListObject = myPathListField.get(dexClassLoader);// 獲取 DexPathList 類Class myPathListClass = myPathListObject.getClass();// 獲取 DexPathList 類中的 private final Element[] dexElements 成員字段Field myDexElementsField =myPathListClass.getDeclaredField("dexElements");// 由于是私有成員字段 , 需要設置可訪問性myDexElementsField.setAccessible(true);// 獲取 DexPathList pathList 對象的 Element[] dexElements 成員Object myDexElementsObject = myDexElementsField.get(myPathListObject);// 自己的 Element[] dexElements 加載完畢-----------------------------------------// 將系統 PathClassLoader pathClassLoader 的// DexPathList pathList 對象的 Element[] dexElements 成員// systemDexElementsObject// 與// 自己在程序中的 DexClassLoader dexClassLoader 的// DexPathList pathList 對象的 Element[] dexElements 成員// myDexElementsObject// 進行融合// 將 myDexElementsObject 插入到 systemDexElementsObject// 獲取 Dex 數組 , Element 類型無法引用 , 不是公開的// 首先獲取 Element 類型// systemDexElementsObjectClass<?> elementClass = systemDexElementsObject.getClass().getComponentType();// 獲取兩個 Element[] dexElements 數組的成員個數// 系統中的 PathClassLoader 中的 Element[] dexElements 數組大小int systemDexCount = Array.getLength(systemDexElementsObject);// 本應用中的 DexClassLoader 中的 Element[] dexElements 數組大小int myDexCount = Array.getLength(myDexElementsObject);Log.i("TAG", "systemDexCount = " + systemDexCount + " , myDexCount = " + myDexCount);// 重新創建一個數組// 類型 : Class<?> elementClass// 長度 : systemDexCount + myDexCountObject elementArray =Array.newInstance(elementClass, systemDexCount + myDexCount);// 填充數組內容, 這里特別注意 , 數組中的元素的順序很重要 ,// 同樣類型的類 , 在多個 Dex 都存在 , 如果在前面的 Dex 中查找到了 , 就不再向后查找了// 修復包的 Dex 要放在最前面 , 這樣才能起到修復作用// 先放置修復包 Dexfor(int i = 0; i < myDexCount; i ++){// 獲取 myDexElementsObject 數組中的第 i 個元素// 放置到 elementArray 數組中的第 i 個元素位置Array.set(elementArray, i,Array.get(myDexElementsObject, i));}// 再放置系統 Dexfor(int i = 0; i < systemDexCount; i ++){// 獲取 systemDexElementsObject 數組中的第 i 個元素// 放置到 elementArray 數組中的第 i + myDexCount 個元素位置Array.set(elementArray,i + myDexCount,Array.get(systemDexElementsObject, i));}// 通過反射方法// 將合并后的 elementArray 數組放置到// PathClassLoader 中的 Element[] dexElements 中systemDexElementsField.set(systemPathListObject, elementArray);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}} }



三、 源碼資源



源碼資源 :

  • GitHub 地址 : https://github.com/han1202012/HotFix
  • CSDN 源碼快照 : 到下一篇博客下載 , 該快照目前還跑不起來 ;

注意 : 此時熱修復還不能生效 , 需要進一步進行分包操作才可以 ;

總結

以上是生活随笔為你收集整理的【Android 热修复】热修复原理 ( 合并两个 Element[] dexElements | 自定义 Application 加载 Dex 设置 | 源码资源 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 好吊日免费视频 | 黑人黄色大片 | 国产xxxxxxxxx | 欧美午夜精品一区 | 91小仙女jk白丝袜呻吟 | 日韩精品在线视频观看 | 成人黄色av网址 | 深夜国产在线 | 好吊色网站| 亚洲福利小视频 | 欧美日韩中文字幕在线视频 | 特级a毛片| 韩国禁欲系高级感电影 | 性做久久久久久免费观看 | 国产男男gay体育生白袜 | 国产欧美日韩综合精品一区二区 | 亚洲热在线观看 | 国产精品一区视频 | 久久国产视频播放 | 毛片网 | av手机在线看 | 中文字幕在线观看一区二区三区 | 精品少妇久久久久久888优播 | 97人妻精品一区二区三区免费 | 亚洲爆乳无码一区二区三区 | 中文字幕视频免费观看 | 免费av网址在线观看 | 97国产精品视频人人做人人爱 | 狠狠干91| 国产精华一区二区三区 | 日韩美女免费视频 | 日韩网站免费观看 | 欧美在线视频精品 | 成人理论视频 | 99在线成人精品视频 | aa丁香综合激情 | 久久久电影 | 欧美精品免费播放 | 亚洲av无码精品一区二区 | 欧美精品在线一区二区 | 色噜噜狠狠一区二区 | 免费视频网站在线观看入口 | 成人123区 | 久久一区二 | 91豆花视频 | 色欲AV无码精品一区二区久久 | 日本在线小视频 | 日韩中文网 | 香蕉视频啪啪 | 人人妻人人澡人人爽人人dvd | 顶臀精品视频www | 肉丝美脚视频一区二区 | 成人拍拍 | 欧美久久久久久久久久久久久久 | 美女撒尿无遮挡网站 | 很黄很黄的网站 | 国产乱码一区二区三区播放 | 黄色欧美网站 | 午夜激情在线观看视频 | 亚洲一区二区三区四区在线观看 | 日本sm调教—视频|vk | 日本h在线观看 | 日本黄色片段 | 青春草在线视频免费观看 | 美丽的姑娘在线观看 | 国产一级在线视频 | 伊人精品影院 | 久久国产人妻一区二区免色戒电影 | 亚洲成人精 | 欧美一区二区三区免费看 | 日韩美女视频一区 | 日本少妇xxx| 久久依人网| 色呦呦中文字幕 | 精品少妇白浆小泬60P | 亚洲黄色片 | 午夜伦伦电影理论片费看 | 久久av红桃一区二区小说 | ass精品国模裸体pics | 免费网站在线高清观看 | 中文字幕精品视频在线观看 | 国产香蕉网 | 久久看片| 欧美一区国产一区 | 777米奇影视第四色 五月丁香久久婷婷 | 天天爱天天做 | 亚洲一区二区三区在线观看视频 | 亚洲啪视频| 亚洲高清在线免费观看 | 精品少妇一区二区 | 亚洲成人高清在线观看 | 99久久精品免费看国产 | 国产毛片毛片毛片毛片毛片 | 四虎影视成人永久免费观看亚洲欧美 | 亚洲精品99久久久久中文字幕 | 蜜桃视频网站 | 久久亚洲精精品中文字幕早川悠里 | 国产亚洲精品aaaaaaa片 | 日韩不卡视频一区二区 |