Administrator
发布于 2026-08-05 / 10 阅读
0
0

Android ClassLoader 介绍

ClassLoader(抽象基类) ← BaseDexClassLoader ← DexClassLoader / PathClassLoader

Java JVM 加载.class字节码;Android ART/Dalvik 加载 dex 文件,ClassLoader 就是用来把 dex 里的 Java 类加载到内存中使用的工具。

继承关系(如图)

  1. ClassLoader:java.lang.ClassLoader,抽象基类,定义类加载基础逻辑,实现双亲委派的 loadClass 逻辑。

  2. BaseDexClassLoader:继承 ClassLoader,Android 加载 dex 的核心实现类,内部持有DexPathList,用来解析 dex/apk/jar,真正做 dex 读取查找类的工作。

  3. 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 默认遵循双亲委派:

  1. 收到加载类请求,先检查自己是否已经加载过该类;

  2. 优先委托父 ClassLoader去加载,向上递归;

  3. 如果所有父加载器都找不到这个类,自己才去尝试 findClass 加载;

  4. 找不到抛出ClassNotFoundException。

好处:

  1. 避免同一个类被多次加载;

  2. 保证系统类安全,防止自定义类替换系统基础类。

BaseDexClassLoader 内部核心:DexPathList

BaseDexClassLoader 内部持有DexPathList,真正解析 dex 文件、查找类的逻辑都在这里。DexPathList 内部维护一组DexFile,对应一个个 dex 文件,findClass 最终调用 DexFile 查找类。

典型应用场景

  1. 热修复:使用 DexClassLoader 加载补丁 dex,替换 bug 类;

  2. 插件化:DexClassLoader 加载外部插件 apk,不安装就运行插件代码;

  3. App 本身:App 运行时,系统 PathClassLoader 加载本 App 的 classes.dex。

小提示:Android8.0 之后,DexClassLoader/PathClassLoader 底层行为有变化,不再需要手动指定 optimizedDirectory,传 null 也可以正常工作,但两者的使用场景习惯依然保留。


评论