类的加载到JVM分为以下五个阶段
一.加载
将二进制流加载到JVM方法区中,并生成一个class文件,作为类的访问入口
1.通过类的全限定名获取类的二进制字节流,(通过文件,网络,二进制流等方法获取)
2.将字节流所代表的静态存储结构转换为运行时数据结构
3.在内存中生成Java.lang.Class对象,作为方法区该类的各种数据的访问入口
二.验证
用来确保二进制流不会危害到JVM系统安全
1.文件格式验证(符合class文件规范),此阶段验证完成二进制流才能进入方法区,因此在加载阶段,此阶段已经开始
2.元数据验证(符合Java语言规范)
3.字节码验证(对方法体进行验证),对输入流,输出流进行验证,确保方法执行不会对虚拟机有害操作
4.符号引用验证(解析动作时发生此验证),能否将符号引用转换成直接引用
三.准备
为类变量分配内存并初始化值(数据类型的默认值),对象成员是在实例化对象之后才有的,因此非成员变量
四.解析
将符号引用(字面量,与内存布局无关)转换成直接引用(指向内存地址)
1.类或接口解析
在类D中将从未解析过的符号引用N解析为类或接口的直接引用C
2.字段解析
3.类方法解析
4.接口方法解析
五.初始化
执行Java程序代码,包括static语句以及静态变量的赋值语句,执行clinit方法过程
1.clinit方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的。定义在静态语句块之后的静态变量,在静态语句块中可以赋值,但不能访问
2.保证子类执行clinit方法之前,父类clinit方法已经执行过
3.如果没有静态语句块和静态变量,则无clinit方法
4.接口不能使用静态语句块,变量默认为静态变量,此项与类不同
5.多线程环境下,只有一个线程执行clinit方法,其他线程阻塞