类加载过程
- 加载
- 验证
- 准备
- 解析
- 初始化
加载
在加载阶段,虚拟机需要完成3件事情:
1、获取类的二进制字节流
2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3、在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
数组的加载有所不同,数组类本身不通过类加载器创建,它是由Java虚拟机直接创建的
验证
这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全,大致上会完成4个阶段:文件格式验证
、元数据验证
、字节码验证
、符号引用验证
。
文件格式验证
验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。该阶段的验证的目的主要是保证输入的字节流能正确地解析并存储于方法区之内,只有通过了这个阶段的验证后,字节流才会进入内存的方法区进行存储,所以后面3个阶段的验证都是基于方法区的存储结构进行的。
元数据验证
对字节码描述的信息进行语义分析,以确保其描述符合Java语言规范的要求。
字节码验证
整个验证过程中最复杂的一个阶段,主要目的是通过数据流和控制流分析,确保程序语义是合法的、符合逻辑的。对类的方法体进行校验分析,保证被校验类的方法在运行时不会做出危害虚拟机安全的事件。
符号引用验证
符号引用验证可以看作是对类自身以外(常量池的各种符号引用)的信息进行匹配性校验。
准备
准备阶段是正式为类变量(static修饰)分配内存并设置类变量初始值(一般是零值)的阶段,这些变量所使用的内存都将在方法区中进行分配。
解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
- 符号引用:与虚拟机实现的内存布局无关,引用的目标也不一定已经加载到内存中。
- 直接引用:可以是直接指向目标的指针、相对偏移量或一个能间接定位到目标的句柄。直接引用的目标必定已经加载在内存中。
初始化
类加载的最后一步,真正执行类中定义的Java程序代码。初始化过程就是执行类构造器<clinit>()方法的过程。
<clinit>()方法是有编译器自动手机类中所有类变量的赋值动作和静态代码块(static{}块)中的语句合并产生的,收集顺序由语句在源文件出现的顺序所决定,它与类的构造函数(<init>())不同,它不需要显示调用父类构造器,虚拟机会保证子类的<clinit>()方法执行之前,父类的<clinit>()方法已经执行完毕。
网友评论