ClassLoader(抽象基类) ← BaseDexClassLoader ← DexClassLoader / PathClassLoader
Java JVM 加载
.class字节码;Android ART/Dalvik 加载 dex 文件,ClassLoader 就是用来把 dex 里的 Java 类加载到内存中使用的工具。
继承关系(如图)

ClassLoader:
java.lang.ClassLoader,抽象基类,定义类加载基础逻辑,实现双亲委派的 loadClass 逻辑。BaseDexClassLoader:继承 ClassLoader,Android 加载 dex 的核心实现类,内部持有
DexPathList,用来解析 dex/apk/jar,真正做 dex 读取查找类的工作。PathClassLoader、DexClassLoader:两者都继承
BaseDexClassLoader,只是构造参数不一样,用途区分。
各个加载器作用
1. PathClassLoader
系统默认应用类加载器,应用安装后,App 运行时默认使用它。
只能加载已经安装到手机上的 apk,不能加载外部未安装的 dex/apk。
构造函数传入
optimizedDirectory为 null,由系统自动处理 dex 优化输出目录。父加载器是
BootClassLoader,用来加载 Android Framework 系统类(Activity、Context 等)。
2. DexClassLoader
可以加载外部存储任意路径的 dex、apk、jar 文件(未安装的包)。
需要手动指定
optimizedDirectory:dex 优化后的 odex/vdex 缓存目录,这个目录必须是应用私有可读写目录。是插件化、热修复技术的核心类加载器,用来动态加载外部插件 apk。
简单对比:
PathClassLoader:只加载已安装 App,系统给 App 默认使用。
DexClassLoader:加载外部 / 未安装 dex/apk,动态加载用。
补充:BootClassLoader
继承 ClassLoader,是 PathClassLoader 的父加载器,负责加载 Android 系统 framework 的类,我们代码一般不会直接使用它。
双亲委派模型
Android ClassLoader 默认遵循双亲委派:
收到加载类请求,先检查自己是否已经加载过该类;
优先委托父 ClassLoader去加载,向上递归;
如果所有父加载器都找不到这个类,自己才去尝试 findClass 加载;
找不到抛出
ClassNotFoundException。
好处:
避免同一个类被多次加载;
保证系统类安全,防止自定义类替换系统基础类。
BaseDexClassLoader 内部核心:DexPathList
BaseDexClassLoader 内部持有DexPathList,真正解析 dex 文件、查找类的逻辑都在这里。DexPathList 内部维护一组DexFile,对应一个个 dex 文件,findClass 最终调用 DexFile 查找类。
典型应用场景
热修复:使用 DexClassLoader 加载补丁 dex,替换 bug 类;
插件化:DexClassLoader 加载外部插件 apk,不安装就运行插件代码;
App 本身:App 运行时,系统 PathClassLoader 加载本 App 的 classes.dex。
小提示:Android8.0 之后,DexClassLoader/PathClassLoader 底层行为有变化,不再需要手动指定 optimizedDirectory,传 null 也可以正常工作,但两者的使用场景习惯依然保留。