05.类加载器深入解析及重要特性剖析
类从加载到运行到销毁过程
类加载器过程
1.加载
- 加载
- 把二进制形式的 Java 类型读入到 Java 虚拟机中
2.连接过程中的 3 个子过程
- 验证
- 对 class 字节码验证
- 准备
- 为类变量分配内存,设置默认值。
- 但是在到达初始化之前,类变量都没有初始化为真正的初始值
- 解析
- 解析过程就是在类型的常量池中寻找类,接口,字段和方法的符号引用,把这些符号引用替换成直接引用的过程
3.初始化阶段
- 初始化
- 为类变量赋予正确的初始值
4.类的实例化
Java 编译器为它编译的每一个类都至少生成一个实例初始化方法,在 Java 的 class 文件中,这个实例初始化方法被称为 <init>
。针对源代码中每一个类的构造方法,Java 编译器都产生一个 <init>
方法。
- 类实例化
- 为新的对象分配内存
- 为实例变量赋默认值
- 为实例变量赋正确的初始值
5.垃圾回收和对象终结
1.类的加载
- 类的加载的最终产品是位于内存中的
Class
对象 Class
对象是反射的入口- Class 对象封装了类在方法区内的数据结构,并且向 Java 程序员提供了访问方法区的数据结构的接口
两种类型的类加载器
Java 虚拟机自带的加载器
- 根类加载器:Bootstrap
- 扩展类加载器:Extension
- 系统 (应用) 类加载器:System
用户自定义的类加载器
java.lang.ClassLoader
的子类- 用户可定制类的加载方式
加载器细节
- 类加载器并不需要等到某个类被“首次主动使用”时再加载它
- JVM 规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程中遇到了 .class 文件缺失或存在错误,类加载器必须在程序首次主动使用时才报告错误(LinkageError错误)
- 如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误
2.类的连接
类的验证
类被加载后,就进入到连接阶段。连接就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去。
类的验证的内容
- 类文件的结构检查
- 语义检查
- 字节码验证
- 二进制兼容性的验证
类的准备
类的解析
3.类的初始化
调用 ClassLoader 类的 loadClass 方法加载一个类,并不是对类的主动使用,不会导致类的初始化
类的初始化步骤
- 假如这个类还没有被加载和连接,那就先进行加载和连接
- 假如类存在直接父类,并且这个父类还没有被初始化,那就先开始初始化直接父类
- 假如类中存在初始化语句,那就依次执行这些初始化语句
类的初始化时机
- 主动使用:7 种
接口的初始化
当 Java 虚拟机初始化一个类时,要求它的所有父类都已经初始化,但是这条规则并不适用于接口
- 在初始化一个类时,并不会先初始化它所实现的接口
- 在初始化一个接口时,并不是先初始化它的父接口
因此一个父接口并不会因为它的子接口或者实现类的初始化而初始化。只有当程序首次使用特定接口的静态变量时,才会导致该接口的初始化。
类加载器
类加载器用于把类加载到 Java 虚拟机种,从 JDK1.2 开始,类的加载过程采用父亲委托级制,这种机制更好的保证了 Java 平台的安全。在此委托机制种,除了 Java 虚拟机自带的根类加载器外,其余的类加载器只有一个父加载器。
当 Java 程序请求加载器 loader1 加载 Sample 类时,loader1 首先委托自己的父亲区加载 Sample 类,若父加载器能加载,则由父加载器完成加载任务,否则才由加载器 loader1 本身完成加载 Sample 类。
没有修不好的电脑