文章目录
Android 插件化系列文章目录
前言
一、通过反射获取 "宿主" 中的 Element[] dexElements
1、反射获取 BaseDexClassLoader.class
2、反射获取 DexPathList pathList 字段
3、反射获取 DexPathList pathList 对象
4、获取 DexPathList pathList 对象
5、反射获取 Element[] dexElements 字段
6、反射获取 Element[] dexElements 对象
二、完整代码示例
前言
在上一篇博客 【Android 插件化】Hook 插件化框架 ( 通过反射获取 “插件包“ 中的 Element[] dexElements ) 介绍了从 " 插件包 " APK 文件中获取 Element[] dexElements 流程 , 本篇博客中介绍获取 “宿主“ 应用中的 Element[] dexElements ;
Android 中的类加载器 DexClassLoader , PathClassLoader 的父类是 BaseDexClassLoader ,
BaseDexClassLoader 中有 private final DexPathList pathList 成员变量 ,
DexPathList 中有 private Element[] dexElements 成员变量 ,
Element[] dexElements 就是最终存放 Dex 字节码数据的内存变量 , 最终将 " 宿主 " 应用中读取的 dexElements 合并到 " 宿主 " 应用的 dexElements 中 ;
获取 " 宿主 " 与 " 插件包 " Element[] dexElements 的区别在于 ,
" 插件包 " 的类加载器是 DexClassLoader , 是由开发者自己创建的 ;
// 创建类加载器 DexClassLoader plugin_dexClassLoader = new DexClassLoader( apkPath, // 插件包路径 cachePath, // 插件包加载时产生的缓存路径 null, // 库的搜索路径, 可以设置为空 mBase.getClassLoader() // 父加载器, PathClassLoader );java
" 宿主 " 应用的类加载器 PathClassLoader 是由 Android 上下文 Context 提供的 , 也就是由系统创建的 ;
PathClassLoader host_pathClassLoader = (PathClassLoader) mBase.getClassLoader();
一、通过反射获取 “宿主” 中的 Element[] dexElements
反射 " 宿主 " 应用的 dexElement 执行步骤 :
① 反射获取 BaseDexClassLoader.class
② 反射获取 BaseDexClassLoader.calss 中的 private final DexPathList pathList 成员字段
③ 获取 PathClassLoader 类加载器中的 DexPathList pathList 成员对象
④ 获取 DexPathList.class
⑤ 反射获取 DexPathList.class 中的 private Element[] dexElements 成员变量的 Field 字段对象
⑥ 反射获取 DexPathList 对象中的 private Element[] dexElements 成员变量对象
1、反射获取 BaseDexClassLoader.class
反射获取 BaseDexClassLoader.class , 通过反射获取插件包中的 dexElements , 这种类加载是合并类加载 , 将所有的 Dex 文件 , 加入到应用的 dex 文件集合中 , 可参考 dex 加固 , 热修复 , 插装式插件化 的实现步骤 ;
反射出 BaseDexClassLoader 类 , PathClassLoader 和 DexClassLoader 都是 BaseDexClassLoader 的子类 ;
代码示例 :
// ① 反射获取 BaseDexClassLoader.class Class<?> host_baseDexClassLoaderClass = null; try { host_baseDexClassLoaderClass = Class.forName("dalvik.system.BaseDexClassLoader"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
2、反射获取 DexPathList pathList 字段
// ② 反射获取 BaseDexClassLoader.calss 中的 private final DexPathList pathList 成员字段 Field host_pathListField = null; try { host_pathListField = host_baseDexClassLoaderClass.getDeclaredField("pathList"); // 设置属性的可见性 host_pathListField.setAccessible(true); } catch (NoSuchFieldException e) { e.printStackTrace(); }
3、反射获取 DexPathList pathList 对象
根据 Field 字段获取 成员变量 , DexClassLoader 继承了 BaseDexClassLoader, 因此其内部肯定有 private final DexPathList pathList 成员变量 ;
// ③ 反射获取 DexClassLoader 类加载器中的 DexPathList pathList 成员对象 // 根据 Field 字段获取 成员变量 // DexClassLoader 继承了 BaseDexClassLoader, 因此其内部肯定有 // private final DexPathList pathList 成员变量 PathClassLoader host_pathClassLoader = (PathClassLoader) mBase.getClassLoader(); Object host_pathListObject = null; try { host_pathListObject = host_pathListField.get(host_pathClassLoader); } catch (IllegalAccessException e) { e.printStackTrace(); }