一个类被加载时的生命周期
- 要是严格意义上划分就可以划分为七个阶段
- 要是不考虑使用 其实可以划分为三阶段 :加载 , 连接 , 初始化
类的加载
- 将类的字节码载入方法区,并创建类.class 对象
- 如果此类的父类没有加载,先加载父类
- 加载是懒惰执行
如果 有 static final 修饰的基本类型,在加载的时候也会一并赋值
这个Class 类对象在堆中, 是作为程序访问方法区中的类型数据的外部接口。
类的验证
验证类是否符合 Class 规范,合法性、安全性检查
( 确保加载的类符合 JVM 规范和安全,保证被校验类的方法在运行时不会做出危害虚拟机的事件,其实就是一个安全检查 )
四个阶段的验证 :
- 文件格式的验证 ,
- 元数据验证 ,
- 字节码验证,
- 符号引用验证
类的准备
为 static 变量分配空间,设置默认值
注意:准备阶段只设置类中的静态变量(方法区中),不包括实例变量(堆内存中),实例变量是对象初始化时赋值的)
类的解析
将常量池的符号引用解析为直接引用
(符号引用比如我现在import java.util.ArrayList这就算符号引用,直接引用就是指针或者对象地址,注意引用对象一定是在内存进行)
- 类和接口的解析
- 字段解析
- 方法解析
类的初始化
- 静态代码块、static 修饰的变量赋值、static final 修饰的引用类型变量赋值,会被合并成一个
<cinit>
方法,在初始化时被调用 - static final 修饰的基本类型变量赋值,在链接阶段就已完成
- 初始化是懒惰执行
类加载器
类加载器就是用来加载类的Class 文件的,每个类都有自己的类加载器,要是相比两个对象想不想等,这两个类必须是同一个 Class 文件才行,被同一个加载器加载。
双亲委派模型
在Java 虚拟机的角度来看类的加载器,主要分为两大类 : 一种是启动类加载器,(Bootstrap ClassLoader) ,这个类加载器使用的是 C++实现 ,另外一类是由 Java 语言实现,独立在Java 虚拟机之外,并且全部继承抽象类 java.lang.ClassLoader
- 启动类加载器 (Bootstrap Class Loader) :加载存放在 lib 下的类
- 扩展类加载器 ( Extension Class Loader) : java.ext.dirs 下类库
- 应用程序类加载器(Application Class Loader) :负责加载用户类的路径下的类
双亲委派 : 当一个类加载器接收到了,类的加载请求,首先不会自己尝试加载这个类,现将请求委派给父类加载器去完成,每一个类加载器都是如此,,因此所有的加载请求都会加载到父类加载器的最顶层,再逐层向下加载,只有父类不能加载的时候,子类才会尝试加载。