Android中的ClassLoader类型和Java中的ClassLoader类型类似,也分为两种类型,分别是系统ClassLoader和自定义ClassLoader。其中系统ClassLoader主要有3种分别是BootClassLoader、PathClassLoader和DexClassLoader。
1.1 BootClassLoader
Android系统启动时会使用BootClassLoader来预加载常用类,与Java中的BootClassLoader不同,它并不是由C/C++代码实现,而是由Java实现的
class BootClassLoader extends ClassLoader {
private static BootClassLoader instance;
@FindBugsSuppressWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED")
public static synchronized BootClassLoader getInstance() {
if (instance == null) {
instance = new BootClassLoader();
}
return instance;
}
}
BootClassLoader是ClassLoader的内部类,并继承自ClassLoader。BootClassLoader是一个单例类,需要注意的是BootClassLoader的访问修饰符是默认的,只有在同一个包中才可以访问,因此我们在应用程序中是无法直接调用的。
1.2 DexClassLoader
DexClassLoader可以加载dex文件以及包含dex的压缩文件(apk和jar文件),不管是加载哪种文件,最终都是要加载dex文件,为了方便理解和叙述,将dex文件以及包含dex的压缩文件统称为dex相关文件。
来查看DexClassLoader的代码,如下所示。
public class DexClassLoader extends BaseDexClassLoader {
55 public DexClassLoader(String dexPath, String optimizedDirectory,
56 String librarySearchPath, ClassLoader parent) {
57 super(dexPath, new File(optimizedDirectory), librarySearchPath, parent);
58 }
59 }
60
DexClassLoader的构造方法有四个参数:
dexPath:dex相关文件路径集合,多个路径用文件分隔符分隔,默认文件分隔符为‘:’
optimizedDirectory:解压的dex文件存储路径,这个路径必须是一个内部存储路径,一般情况下使用当前应用程序的私有路径:/data/data/<Package Name>/...。
librarySearchPath:包含 C/C++ 库的路径集合,多个路径用文件分隔符分隔分割,可以为null。
parent:父加载器。
DexClassLoader 继承自BaseDexClassLoader ,方法实现都在BaseDexClassLoader中。
1.3 PathClassLoader
Android系统使用PathClassLoader来加载系统类和应用程序的类,来查看它的代码:
public class PathClassLoader extends BaseDexClassLoader {
26 /**
27 * Creates a {@code PathClassLoader} that operates on a given list of files
28 * and directories. This method is equivalent to calling
29 * {@link #PathClassLoader(String, String, ClassLoader)} with a
30 * {@code null} value for the second argument (see description there).
31 *
32 * @param dexPath the list of jar/apk files containing classes and
33 * resources, delimited by {@code File.pathSeparator}, which
34 * defaults to {@code ":"} on Android
35 * @param parent the parent class loader
36 */
37 public PathClassLoader(String dexPath, ClassLoader parent) {
38 super(dexPath, null, null, parent);
39 }
40
41 /**
42 * Creates a {@code PathClassLoader} that operates on two given
43 * lists of files and directories. The entries of the first list
44 * should be one of the following:
45 *
46 * <ul>
47 * <li>JAR/ZIP/APK files, possibly containing a "classes.dex" file as
48 * well as arbitrary resources.
49 * <li>Raw ".dex" files (not inside a zip file).
50 * </ul>
51 *
52 * The entries of the second list should be directories containing
53 * native library files.
54 *
55 * @param dexPath the list of jar/apk files containing classes and
56 * resources, delimited by {@code File.pathSeparator}, which
57 * defaults to {@code ":"} on Android
58 * @param librarySearchPath the list of directories containing native
59 * libraries, delimited by {@code File.pathSeparator}; may be
60 * {@code null}
61 * @param parent the parent class loader
62 */
63 public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
64 super(dexPath, null, librarySearchPath, parent);
65 }
PathClassLoader继承自BaseDexClassLoader,实现也都在BaseDexClassLoader中。 PathClassLoader的构造方法中没有参数optimizedDirectory,这是因为PathClassLoader已经默认了参数optimizedDirectory的值为:/data/dalvik-cache,很显然PathClassLoader无法定义解压的dex文件存储路径,因此PathClassLoader通常用来加载已经安装的apk的dex文件(安装的apk的dex文件会存储在/data/dalvik-cache中)。
Android ClassLoader的继承关系
- ClassLoader是一个抽象类,其中定义了ClassLoader的主要功能。BootClassLoader是它的内部类。
- SecureClassLoader类和JDK8中的SecureClassLoader类的代码是一样的,它继承了抽象类ClassLoader。SecureClassLoader并不是ClassLoader的实现类,而是拓展了ClassLoader类加入了权限方面的功能,加强了ClassLoader的安全性。
- URLClassLoader类和JDK8中的URLClassLoader类的代码是一样的,它继承自SecureClassLoader,用来通过URl路径从jar文件和文件夹中加载类和资源
- InMemoryDexClassLoader是Android8.0新增的类加载器,继承自BaseDexClassLoader,用于加载内存中的dex文件。
- BaseDexClassLoader继承自ClassLoader,是抽象类ClassLoader的具体实现类PathClassLoader和DexClassLoader都继承它。
BootClassLoader和PathClassLoader的创建
BootClassLoader是在Zygote进程的入口main方法中preload(bootTimingsTraceLog)创建的,PathClassLoader则是在Zygote进程创建SystemServer进程时创建的