类加载器
在Android中,类加载器(ClassLoader)是一个重要的组件,负责在运行时动态加载JVM和Android类库。Android的类加载器系统基于JVM的类加载器模型,但有一些特定的调整和优化,以适应Android平台的需要。
(1) Bootstrap ClassLoader:
- 这是最顶层的类加载器,由JVM实现。
- 主要加载Java和Android核心类库。
- 通常通过null作为父加载器。
(2) PathClassLoader(或DexClassLoader):
- Android特有的类加载器,用于从APK文件、DEX文件或JAR/ZIP文件中加载类。
- PathClassLoader是Android应用默认的类加载器,用于加载应用的类和资源。
DexClassLoader是PathClassLoader的一个子类,提供了从指定的路径加载DEX文件的能力,动态加载插件或模块化场景常用加载器。
可以发现PathClassLoader和DexClassLoader源码很简单,只包含了一个构造函数,去调用父类BaseDexClassLoader(所有的工作都应该是在BaseDexClassLoader里完成的了)。而这两个加载器不同的是PathClassLoader的构造中少了optimizedDirectory这个参数,原因是PathClassLoader是加载/data/app中的apk,也就是系统中的apk,而这部分的apk都会解压释放dex到指定的目录中,这个操作由系统完成,不需要单独传入路径,而DexClassLoader传入,用来缓存需要加载的dex文件,并创建一个DexFile对象,如果为null,会直接使用dex文件原有路径创建DexFile(这个参数已经弃用,自API26起无效)。
(3) System ClassLoader(或AppClassLoader):
- Android系统的应用类加载器,继承自URLClassLoader。
- 用于加载Android系统的类和应用的类。
- 在Android中不直接引用System ClassLoader或AppClassLoader,通过ClassLoader.getSystemClassLoader()获取。
(4) 自定义ClassLoader:
- 可以继承ClassLoader类或其子类(如DexClassLoader)来创建自定义的类加载器。
- 自定义类加载器可以用于加载网络上的类、从数据库加载加密的类、或者实现更复杂的类加载逻辑。
类加载器的主要用途:
- 动态加载和执行代码,如插件化开发、热更新等。
- 加载和执行不同来源的代码,如从网络下载的JAR包或DEX文件。
- 隔离不同来源的代码,防止类冲突和安全问题。
注意:滥用类加载器可能导致内存泄漏和性能问题。在使用类加载器时,应该仔细考虑其生命周期和资源管理。
DexPathList
DexPathList是DexClassLoader和BaseDexClassLoader等类加载器用于处理DEX文件路径的一个内部类。当使用DexClassLoader或BaseDexClassLoader加载DEX文件时,DexPathList起到了关键的作用。
(1) 作用:DexPathList负责管理和维护DEX文件的路径信息,使类加载器能够正确地找到并加载DEX文件中的类。
(2) 构造:DexPathList在DexClassLoader或BaseDexClassLoader的构造函数中被创建。构造DexPathList时,需要提供DEX文件的路径、优化目录、库路径以及父类加载器等参数。
(3) 成员变量:DexPathList有一个私有的final成员变量dexElements,是一个Element数组,包含了所有DEX文件的Element对象,每个Element对象对应一个DEX文件。
(4) 加载DEX文件:在DexPathList的构造函数中,会调用makeDexElements()方法来加载DEX文件。这个方法会遍历提供的DEX文件路径列表,并为每个DEX文件创建一个Element对象,然后将这些Element对象添加到dexElements数组中。
(5) 加载类:当类加载器需要加载一个类时,会通过DexPathList的loadClass()方法来实现。这个方法会遍历dexElements数组中的每个Element对象,并尝试从对应的DEX文件中加载类。一旦找到需要加载的类,就会返回该类的Class对象。
(6) 优化:为了提高性能,DexPathList还支持DEX文件的优化。在加载DEX文件时,可以将DEX文件优化到指定的目录中,以减少内存占用和提高加载速度。