一,BaseDexClassLoader
是如何创建DexElements的?makeDexElements的实现细节:
1.针对如何创建DexElements的,
BaseDexClassLoader这个类有三种构造方法,只分析两个(因为另外一个只不过是其中一个的扩展,对于加载DexElements的方式并没有改变)。首先parent不能少,接下来的属性就是两种创建DexElements的不同方式,其中一个构造方法是传入bytes数组,另外两个是用的dexFilePath(除此之外构造方法还需要很多参数,但对于这个问题是没有必要的)。传入的如果是bytes数组的话会调用 makeInMemoryDexElements,而如果是dexPath的话就是调用makeDexElements这个方法来创建DexElements的。
2.实现细节:
创建ClassLoader时会创建DexElement数组,也就是Dex数组。创建的时候都会创建一个异常类型的集合当加载DexFile出错的时候就会添加到这个集合中,构造方法执行完然后在读这个异常集合里面的数据进行保存到本地变量中。创建Element数组的情况根据ClassLoader的两个构造方法也会有两种情况:
如果是dexPath会进行对传入的DexClassLoader的文件目录进行解析成一个个File集合,然后调用makeDexElements创建element数组。
所以Dex即Element有这样三种情形被添加到Element数组中:
1、遍历到文件夹创建一个Element,传入的参数为遍历的参数File
2.遍历到文件,碰到的是以.dex结尾的文件进行调用loadDexFile加载DexFile结构,如果不为空接着创建Element传入DexFile结构和一个null(这个代表的是后缀为dex文件成功加载进内存)3.遍历到文件,但是不是以.dex文件结尾的,依然调用loadDexFile加载DexFile结构,不管为不为空都创建一个Element,但是空的话传入的参数为遍历的参数File;不为空的话创建将dexFile属性传入并且在传入参数File(这个代表的是不是.dex后缀的文件成功加载到内存)。
综合分析:Element 有两个构造方法:第一个构造方法接受一个参数为解析后的dex文件的File对象第二个构造方法比第一个多了一个参数,第一个参数是dexFile对象,第二个属性和第一个构造方法一样
如果是byte数组的话,会手动进行创建DexFile区别于dexPath的利用loadDexFile,这种情况下会直接创建Element(已经转换为字节了不需要进行校验了将校验过程延后),也就是.dex文件成功加载到了内存中
二,loadDexFile实现细节
如果没有传入优化后的odex文件的路径,直接创建一个DexFile(遍历到的dex文件,类加载器,dex转换后的Element数组【开始遍历的时候会创建一个空的Elements数组,不断遍历进行添加直至所有dex文件全部加载完】)返回;【Element中存放的为DexFile对象创建的时候会传入进去】
传入odex文件存放路径会使用DexFile.loadDex进行创建DexFile结构。
最后会进入到native层去加载