JVM的类加载器:
- Bootstrap ClassLoader 引导类加载器:C/C++代码实现的加载器,用于加载制定的JDK核心库,比如java.lang.*、java.util.*等这些系统类。Java虚拟机的启动就是通过Bootstrap,该ClassLoader在java里无法获取,负责加载/lib下的类
- Extensions ClassLoader 拓展类加载器:Java中的实现类为ExtClassLoader,提供了除了系统类之外的额外功能,可以在java里获取,负责加载/lib/ext下的类
- Application ClassLoader 应用程序类加载器:Java中的实现类为APPClassLoader,是与我们接触最多的类加载器,开发人员写的代码默认就是它来加载,ClassLoader.getSystemClassLoader返回的就是它。
- 自定义类加载器:只需要通过继承java.lang.ClassLoader类的方式来实现自己的类加载器即可。
加载器的加载顺序:
加载顺序:
- BootStrap ClassLoader
- Extension ClassLoader
- APPClassLoader
双亲委派
如果一个类加载器收到了类加载请求,他并不会自己先去加载,而是把这个请求委托给父类加载器去执行,如果父类加载器还存在父类加载器,则进一步向上委托,依次递归,请求最终会到达顶层的启动类加载器,如果父类加载器可以完成加载任务,就成功返回,如果父类加载器无法完成加载任务,子加载器才会尝试去自己加载,这就是双亲委派模式,即每个儿子接到工作都会给父亲去干,当父亲干不了时,再自己去尝试干。
双亲委派的存在原因:
- 避免重复加载,如果加载过一次Class,可以直接读取已经加载的Class
- 更加安全,无法自定义类来替代系统的类,可以防止核心API库被随意篡改
类加载时机:
- 隐式加载:
- 创建类的实例来初始化某个类的子类
- 显式加载:通过反射来加载我们已知的类来加载:
- 使用LoadClass()加载
- 使用forName()加载
类加载流程:
- 装载:查找和导入Class文件
- 链接:其中解析步骤是可以选择的
- 检查:检查载入的class文件数据的正确性
- 准备:给类的静态变量分配储存空间
- 解析:将符号引用转成直接引用
- 初始化:即调用<clinit>函数,对静态变量,静态代码块执行初始化工作
其中1、2步骤并未类中的函数进行任何调用
Android系统中的ClassLoader:
ClassLoader.java为抽象类,BootClassLoader是预加载常用类,单例模式。与Java中的BootClassLoader不同,它并不是用C/C++代码实现的,而是由Java实现的。
SecureClassLoader继承了抽象类ClassLoader,拓展了ClassLoader类,加入了权限方面的功能,其子类URLClassLoader是由URL路径从jar文件中加载类和资源。
BaseDexClassLoader是PathClassLoader、DexClassLoader、InMemoryDexClassLoader的父类,类加载的主要逻辑都是在BaseDexClassLoader中完成的。
PathClassLoader是Android默认使用的类加载器,一个apk中的Activity等类便是其加载。
DexClassLoader可以加载任意目录下的dex、jar、apk、zip文件,比PathClassLoader更灵活,是实现插件化、热修复以及dex壳的重点。
InMemoryDexClassLoader从内存中加载Dex文件
标签:脱壳,java,ClassLoader,基础知识,Java,Android,父类,加载 From: https://www.cnblogs.com/YoungPionner/p/17304705.html