类加载与验证:ClassLoader 与 PathClassLoader
2026/8/9大约 3 分钟运行时Android 14类加载ClassLoaderART
类加载与验证:ClassLoader 与 PathClassLoader
上一章看了 GC。这一章回答:类从哪里加载,ClassLoader 体系是什么,验证在加载中 做什么,类找不到怎么排查?
找到字节码之后仍需验证与链接
| 常见误解 | 正确理解 |
|---|---|
| ClassLoader 只有一个 | 有 BootClassLoader、PathClassLoader 等分层体系 |
| 类加载 = 读文件 | 还要链接与验证,验证失败类不可用 |
| 类找不到就是缺类 | 可能是依赖、混淆、验证或 classpath 问题 |
核心结论
- Android ClassLoader 分层:BootClassLoader、PathClassLoader 等。
- 双亲委托:先让父加载器尝试,找不到再自己加载。
- 加载后要链接与验证,验证失败类不可用。
- 应用类由 PathClassLoader 从 dex 加载。
- 类找不到按“谁声明、谁提供、验证过不过”排查。
类加载主链
逐步解释:
- 请求:代码引用类。
- 委托:父加载器先找。
- 加载:PathClassLoader 读 dex。
- 验证:链接与验证。
- 结果:可用或报错。
双亲委托为什么重要
双亲委托避免重复加载并保证核心类一致:系统类先由 BootClassLoader 提供,应用类 才由 PathClassLoader 兜底。这也意味着“同名类”在不同加载器下是不同对象,热修复 插件常利用这一特性。
源码证据
阅读目标:确认类加载入口。
正文指针:ClassLoader.java(Java);ART 侧 class_linker.cc 的加载与验证。
// ClassLoader.java(伪代码,行号以 r75 为准)
protected Class<?> loadClass(String name) {
// 双亲委托加载
}这段代码证明: Java 层定义委托逻辑;ART 的 ClassLinker 负责实际加载与验证, 两层协作完成类解析。
验证与排障
环境:开发设备或模拟器;以下命令不需要 root。
adb shell dumpsys package <包名> | grep -E "codePath|classLoaderName"
adb logcat -v threadtime | grep -E "ClassNotFound|NoClassDefFound|Verification"
adb shell pm path <包名>先确认类应在的 dex/包是否就位,再看加载与验证日志。类找不到按“声明方、提供方、 验证”三步排查,混淆与依赖冲突是常见原因。
常见误区
- “ClassLoader 只有一个”:分层体系。
- “加载就是读文件”:还要链接验证。
- “类找不到就是缺类”:依赖、混淆、验证都可能。
- “双亲委托可以绕过”:它决定加载顺序。
延伸问题
- 热修复如何利用 ClassLoader 替换类?
- 混淆后类名变化如何影响排查?
- 隐藏 API 限制与类加载的关系是什么?
- 多 dex 如何被 PathClassLoader 管理?
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
ClassLoader.java | loadClass() | 委托逻辑 |
PathClassLoader.java | dex 加载 | 应用类 |
art/runtime/class_linker.cc | 加载验证 | ART 侧 |
pm path | 命令行 | 排障 |
公共路径:libcore/ 与 art/runtime/。行号以 r75 检索为准。
需要从现象反查具体阶段时,见 运行时问题排查。