首先我们来看看下面代码
我们知道,在Java中,类的加载是使用的委托机制,上面的代码就是打印ClassLoader的委托关系。它的运行结果如下:
可以看到,我们应用的加载器是PathClassLoader,它的父加载器是BootClassLoader。下面我们通过代码来进行分析。
一、bootstrap class loader的初始化过程
system/framework/路径对应的就是BOOTCLASSPATH,对应系统相关jar包,在启动虚拟机之后,就需要对其进行加载,其实可以将其理解为顶层ClassLoader加载的相关jar包。
1、读取BOOTCLASSPAT
2、初始化bootstrap class loader
上面的过程就是加载BOOTCLASSPATH下所有的jar和dex文件,并且每个jar或者dex文件都被一个ClassPathEntry引用,最终形成一个ClassPathEntry数组。
ClassPathEntry数组被gDvm.bootClassPath所引用,gDvm是一个全局变量。如下图所示:
所以,如果我们需要加载这些jar文件中的某个类,我们就需要对整个数组进行遍历来获取对应的类的信息。其实BootClassLoader对类的查找过程就是遍历的整个数组来查找的,后面会具体介绍。所以,我们可以将它们对应到BootClassLoader中。
二、应用ClassLoader的创建过程
我们从Application的创建过程说起,直接看看ActivityThread.java
可以看到,我们应用的ClassLoader的父ClassLoader就是BootClassLoader,这个也验证了前文开始的测试结果。
三、BootClassLoader的findClass的调用过程
下面说说BootClassLoader的findClass的调用过程,它跟PathClassLoader或者DexClassLoader的findClass的调用过程不同。
整个过程就是遍历gDvm.bootClassPath对应的ClassPathEntry数组进行查找。gDvm.bootClassPath的ClassPathEntry数组就是bootstrap class loader的初始化过程加载的系统jar文件。
四、PathClassLoader或者DexClasLoader的findClass的调用过程
整个过程就是前面一篇文章Dalvik虚拟机中Java类的加载过程讲过了,这里直接放一张图。
双亲委派机制就是首先在父ClassLoader中进行类查找,一步步深入,如果没有找到就在自己的ClassLoader的查找,如下图所示。
总结
上面对Android中Dalvik虚拟机中ClassLoader创建过程进行了讲解,主要分为两个部分,一个是bootstrap class loader,它在Java中对应的是BootClassLoader,一个是PathClassLoader或者DexClassLoader,它们的findClass是不同的,原因很简单,因为它们查找的范围是不一样的,一个是从系统的jar或者dex中进行查找,一个是从自己的加载的dex中进行查找,而整个查找过程使用的就是双亲委托机制。