前言:在目前的市面项目开发中普遍的在使用一些大牛或者团队开源的框架可以更加保证项目产品的高效稳定迭代,比如之前说过的apk增量更新、热修复等等。在这些框架的原理里都没有绕过Android的类加载这一块,或者说也都是通过对类加载的流程做了一定的干预和插入才最终实现了想要的效果。所以今天我也抽时间再次回头学习学习类加载这块的知识。
先简单介绍一下相关的概念吧。
类加载器是干什么的?
类的加载是由类加载器完成的,类加载器包括:启动类加载器(BootStrap)、扩展类加载器(ExtClassLoader)、应用程序类加载器(AppClassLoader)和自定义类加载器(java.lang.ClassLoader的子类)。
- 启动类加载器: 一般用本地代码实现,负责加载JVM基础核心类库,即 JAVA_HOME\lib 目录下的类。
- 扩展类加载器: 继承自启动类加载器,加载 \lib\ext 下的类,或者被 java.ext.dirs 系统变量指定的类。
- 应用程序类加载器: 继承自扩展类加载器,加载 ClassPath 中的类,或者系统变量 java.class.path 所指定的目录中记载类,是用户自定义加载器的默认父加载器。
- 自定义类加载器 :继承自 ClassLoader 类。
为什么需要自定义类加载器呢?
一方面是由于java代码很容易被反编译,如果需要对自己的代码加密的话,可以对编译后的代码进行加密,然后再通过实现自己的自定义类加载器进行解密,最后再加载。
另一方面也有可能从非标准的来源加载代码,比如从网络来源,那就需要自己实现一个类加载器,从指定源进行加载。
类加载机制是什么?
1.全盘负责
当一个类加载器负责加载某个 Class 时,该 Class 所依赖的和引用的其他 Class 也将由该类加载器负责载入,除非显式指定另外一个类加载器来载入。
2.双亲委派模型
如果一个类加载器收到了 Class 加载的请求,它首先不会自己去尝试加载这个 Class ,而是把请求委托给父加载器去完成,依次向上。因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的 Class 时,即无法完成该加载,子加载器才会尝试自己去加载该 Class 。
这样做的好处是:
1. 可以避免同一个类被多次加载 ;
2. 更加安全,Java 核心 API 中定义的类不会被随意替换 ;
3. 可以保证每个加载器只能加载自己范围内的类;
3.缓存机制
所有加载过的 Class 都会被缓存,当程序中需要使用某个 Class 时,类加载器先从缓存区寻找该 Class ,只有当缓存区不存在时,系统才会去读取该 Class 对应的二进制数据,并将其转换成 Class 对象,存入缓存区。
这就是为什么修改了 Class 后,必须重启JVM,程序的修改才会生效的原因。
类加载器中的四个重要方法
1、loadClass(String name, boolean resolve)
protected Clas