Android BaseDexClassLoader源码阅读
BaseDexClassLoader, 安卓类加载体系核心。用于从包含dex文件的APK中加载类。是专门处理dex文件的类加载器(dex文件是Android 平台的可执行字节码文件,后面有时间再研究)。 这个类有几个子类PathClassLoader、DexClassLoader、InMemoryDexClassLoader、DelegateLastClassLoader,后面详细研究。
看下BaseDexClassLoader有哪些重要的变量和方法:
1、private final DexPathList pathList;

负责管理所有 dex 文件路径和 native 库路径。这是核心的类加载组件。APK中的Java类主要是通过BaseDexClassLoader中的pathList成员加载出来的。
2、sharedLibraryLoaders

一组类加载器,用于加载类和资源,pathList中的代码依赖这些类和资源。用于实现共享库(在Android系统中,共享库相关的类指的是那些由系统提供、可被多个应用程序共同使用的Java类库。这些库中的类并不是每个应用单独打包一份,而是作为系统级的资源存在。通常是在应用的AndroidManifest.xml文件中使用<uses-library>标签声明依赖的共享库)。这是一个数组,专门用于存储共享库的类加载器。 该加载器优先级高于pathList。
3、sharedLibraryLoadersAfter

一组类加载器,和sharedLibraryLoaders相同,区别就是,当搜索类和资源,这些类加载器的优先级是在pathList之后。
4、构造方法。
有几个构造方法最终都调用下面这个:

参数说明:
1)dexPath dexPath 包含dex文件的路径列表,多个路径用文件分隔符分割。
2)librarySearchPath 包含c/c++库的路径集合
3)parent 父加载器
4)sharedLibraryLoaders、sharedLibraryLoadersAfter 共享库
然后再调用reportClassLoaderChain方法,该方法用于报告类加载器的构造信息,记录当前类加载器和父类委托链的结构。主要是framework需要监听dex文件使用,reporter注释如下:

另外,还有一个单独构造方法,参数比较少,如图,不详述了:

5、findClass
之前由ClassLoader源码得知,当父加载器没加载成功时,调用findClass。这个是核心方法。代码如下:


由代码看出类加载流程如下:
1)、优先使用sharedLibraryLoaders共享库的类加载器加载类,如果加载成功直接返回加载好的class对象。如果加载失败,继续下面流程。
2)、调用pathList.findClass(name, suppressedExceptions); 遍历每个dex文件,尝试从dex文件加载指定类。一旦从某个dex文件加载指定类成功了,直接返回这个class对象。如果这一步加载失败,继续下面流程。
3)、使用sharedLibraryLoadersAfter共享库的类加载器加载类,如果加载成功直接返回加载好的class对象。如果加载失败,继续下面流程。
4)、以上流程加载指定类都没成功,抛异常。
6、findLibrary

返回native库的绝对路径。用于查找native库文件(如.so文件)
7、addDexPath

添加dex文件路径
8、addNativePath

添加native库路径
9、findResource

查找资源,优先级:sharedLibraryLoaders > pathList > sharedLibraryLoadersAfter
10、findResources


返回资源枚举集合。资源是从sharedLibraryLoaders、pathList、sharedLibraryLoadersAfter中获取资源URL。
11、getPackage


根据类名获取package对象。
12、getLdLibraryPath

获取native库的搜索路径列表。
ok. 捋清楚了大致流程。pathList里面详细加载类的流程后面再研究。
