文章目录
一、BaseDexClassLoader 构造函数
二、DexPathList 构造函数
三、DexPathList.makeInMemoryDexElements 函数
一、BaseDexClassLoader 构造函数
在上一篇博客 【Android 逆向】ART 脱壳 ( InMemoryDexClassLoader 脱壳 | 加固厂商在 ART 下使用的两种类加载器 | InMemoryDexClassLoader 源码 ) 分析到 , 在 InMemoryDexClassLoader 类加载器中 , 调用了父类 BaseDexClassLoader 的 2 22 个参数的构造函数 ;
BaseDexClassLoader 构造函数如下 , 在该构造函数中创建了 DexPathList 对象 , 并赋值给了 pathList 成员 ;
BaseDexClassLoader 构造函数源码 :
/** * 用于各种基于dex的数据库之间的通用功能的基类 * {@link ClassLoader}实现。 */ public class BaseDexClassLoader extends ClassLoader { private final DexPathList pathList; /** * 构造一个实例。 * * dexFile 必须是完整dexFile的内存表示形式。 * * @param dexFiles 包含类的内存中dex文件数组。 * @param parent 父类加载器 * * @隐藏 */ public BaseDexClassLoader(ByteBuffer[] dexFiles, ClassLoader parent) { // TODO 我们应该支持给它一个库搜索路径。 super(parent); // ★ 核心跳转 this.pathList = new DexPathList(this, dexFiles); } }
源码路径 : /libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
二、DexPathList 构造函数
在 DexPathList 构造函数中 , 调用了 makeInMemoryDexElements 方法创建 DEX 相关的 Element 元素 ;
/** * 一对条目列表,与{@code ClassLoader}关联。 * 其中一个列表是索引/资源路径&mdash;通常提及 * 作为“类路径”&mdash;列表和其他名称目录 * 包含本机代码库。类路径条目可以是以下任一项: * 一个{@code.jar}或{@code.zip}文件,其中包含一个可选的 * 顶级{@code classes.dex}文件以及任意资源, * 或者是一个普通的{@code.dex}文件(不可能与 * 资源)。 * * <p>此类还包含使用这些列表进行查找的方法 * 课程和资源</p> */ /*package*/ final class DexPathList { /** * 构造一个实例。 * * @param definingContext 任何尚未解析的 * 应该定义类 * * @param dexFiles 包含我们应该从中加载类的dex文件的字节缓冲区。 */ public DexPathList(ClassLoader definingContext, ByteBuffer[] dexFiles) { if (definingContext == null) { throw new NullPointerException("definingContext == null"); } if (dexFiles == null) { throw new NullPointerException("dexFiles == null"); } if (Arrays.stream(dexFiles).anyMatch(v -> v == null)) { throw new NullPointerException("dexFiles contains a null Buffer!"); } this.definingContext = definingContext; // TODO It might be useful to let in-memory dex-paths have native libraries. this.nativeLibraryDirectories = Collections.emptyList(); this.systemNativeLibraryDirectories = splitPaths(System.getProperty("java.library.path"), true); this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories); ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>(); // ★ 核心跳转 this.dexElements = makeInMemoryDexElements(dexFiles, suppressedExceptions); if (suppressedExceptions.size() > 0) { this.dexElementsSuppressedExceptions = suppressedExceptions.toArray(new IOException[suppressedExceptions.size()]); } else { dexElementsSuppressedExceptions = null; } } }
源码路径 : /libcore/dalvik/src/main/java/dalvik/system/DexPathList.java
三、DexPathList.makeInMemoryDexElements 函数
在 makeInMemoryDexElements 方法中 , 根据内存中的字节数组数据 , 获取 DexFile , 将内存数据传入了 DexFile 的构造函数 ;
注意 : 传入 DexFile 构造函数的数据是 ByteBuffer buf 类型数据 ;
// ★ 核心跳转 DexFile dex = new DexFile(buf);
DexPathList.makeInMemoryDexElements 函数源码 :
/*package*/ final class DexPathList { private static Element[] makeInMemoryDexElements(ByteBuffer[] dexFiles, List<IOException> suppressedExceptions) { Element[] elements = new Element[dexFiles.length]; int elementPos = 0; for (ByteBuffer buf : dexFiles) { try { // ★ 核心跳转 DexFile dex = new DexFile(buf); elements[elementPos++] = new Element(dex); } catch (IOException suppressed) { System.logE("Unable to load dex file: " + buf, suppressed); suppressedExceptions.add(suppressed); } } if (elementPos != elements.length) { elements = Arrays.copyOf(elements, elementPos); } return elements; } }