1. Android类加载机制
1.1 JVM类加载器(ClassLoader)
- Bootstrap ClassLoader => C++实现
- Extension ClassLoader => ExtClassLoader实现类
- Application ClassLoader => AppClassLoader实现类
- 自定义ClassLoader(只需要继承java.lang.ClassLoader类)
双亲委派
工作原理
如果一个类收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父亲的加载器去执行,如果父亲加载器还存在着其父类加载器,则进一步向上委托,依次递归,请求最终到达顶层的启动类加载器,如果父类加载器可以完成加载任务,就成功返回,倘若父亲加载器无法完成此任务,子类才会自己去尝试加载。
优点
- 避免重复加载,如果已经加载过一次Class,可以直接读取已经加载过的Class
- 更加安全,无法自定义类来代替系统的类,防止核心API库被篡改
类加载时机
隐式加载
- 创建类的实例
- 访问类的静态变量、为静态变量赋值
- 调用类的静态方法
- 使用反射的方式强制创建某个类或者java.long.Class对象
- 初始化某个类的子类
显式加载
- 使用LoadClass()加载
- 使用forName()加载
类加载步骤
- 装载:查找和导入Class文件
- 链接:解析步骤可以选择
- 检查:检查载入的Class文件数据的正确性
- 准备:给类的静态变量分配存储空间
- 解析:将符号转为直接引用
- 初始化:调用
<client>
(编译器生成)函数,对静态变量,静态代码块的初始化工作
1.2. Android类加载
8个ClassLoader解析
- 顶层ClassLoader:为抽象类
- BootClassLoader预加载常用类,单例模式。与Java 中的Bootstrap Class Loader不同,它并不是由C++实现,而是由代码实现。
- BaseDexClassLoader是PathClassLoader、DexClassLoader、InMemoryClassLoader的父类,类加载的主要逻辑都是在BaseDexClassLoader中实现的。
- PathClassLoader是Android默认使用的类加载器,一个apk中的Activity等是在其中加载
- DexClassLoader可以加载任何目录下的dex/jar/apk/zip文件,比PathClassLoader更灵活,是实现插件化,热修复以及dex加壳的重点
- InMemoryClassLoader是Android8.0新引入,直接从内存中加载dex
- SecureClassLoader继承抽象类ClassLoader,扩展ClassLoader在权限方面的功能,加强了安全性,其子类URLClassLoader是用URL路径从Jar文件中加载类和资源。
安卓源码分析
ClassLoader.java
1 | // 用于双亲委派机制,并且每个ClassLoader通过final只能赋值一次 |
BaseDexClassLoader.java
ClassLoader实战查看
验证双亲委派的关系
1 | public void testClassLoader(){ |
DexClassLoader实战
- 首先加入SD卡读写权限
<uses-permission-sdk-23 android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission-sdk-23>
<uses-permission-sdk-23 android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission-sdk-23>