下图是Java类加载的流程图:
我们定义一个CustomClassLoader加载器,去加载String.class文件的流程如下:
【注意】需要注意的是,每一级的ClassLoader进行.class文件的加载,都是从系统指定的路径中findClass进行加载(BootClassLoader和PathClassLoader),一般来说ClassLoader加载失败是因为当前ClassLoader的指定目录下没有该.class文件存在。
双亲委派的作用
Android中使用的类加载器主要包括PathClassLoader和DexClassLoader两个,这两个加载器在Android8以后已经完全一样了,他们都是继承自BaseClassLoader。
Android中进行类加载的时候,最终会首先将所有的.class文件按照dex文件加载到dexElements数组中,这里的dex文件可以理解为一个文件夹,每个dex文件中包含多个.class文件,关于dex文件的加载,我们需要知道:
1. 当ClassLoader要加载一个class的时候,会通过findClass遍历当前的class文件在哪个dex文件中,然后加载该dex文件。这样做的缺点是当一个class在后面的dex文件夹中的时候,遍历加载起来就比较耗时。所以App在启动优化的时候,会将所有主页面用到的类全部放到第一个dex文件中,这样就可以提高App启动的速度;
2. ClassLoader在加载class的时候,要是有两个dex中包含了相同的.class文件,ClassLoader会按照顺序优先的原则加载class,即真正被加载的class是位置在前面的那个dex中的class文件。基于这一点可以实现Android代码热修复,我们可以将需要修复的class文件整体打包成一个dex文件,并放置到dexElements数组的最前面,这样就实现了类的替换加载的功能。