类加载全过程:
类加载:(被加载到内存中开始-到卸载出内存为止)
生命周期:
加载-》验证-》准备-》解析-》初始化-》使用-》卸载
特点:
按照顺序开始,而不是按顺序进行或完成
静态绑定:即前期绑定。在程序执行前方法已经被绑定,此时由编译器或其他链接程序实现。
针对java,可以理解为程序编译器的绑定。java当中只有final、static、private和构造方法是前期绑定的
动态绑定:即晚期绑定,也叫运行时绑定。在运行时根据具体对象的类型进行绑定。在java中几乎所有的方法都是后期绑定的
加载:
需要完成:
1. 通过一个类的权限定名来获取定义此类的二进制字节流
2. 将这个字节所代表的静态存储结构转化为方法区的运行时数据结构。
3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
验证:
是连接阶段的第一步:连接阶段是:验证,准备,解析
目的:
为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求
验证动作:文件格式验证(基于二进制字节流,后面三个是基于方法区的存储结构),元数据验证,字节码验证,符号引用验证
文件格式验证目的:保证输入的字节流能正确的解析并存储于方法区之内,格式上符合描述一个java类型信息的要求。
元数据验证目的:对类的元数据信息进行语义校验,保证不存在不符合java语言规范的元数据信息
字节码验证目的:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。
- 符号引用验证目的:确保解析动作能正常执行。
准备:
正式为类变量分配内存并设置类变量初始值的阶段。
这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随对象一起分配到java堆。
如果字段中存在ConstantValue属性,在准备阶段会被初始化为ConstantValue属性(final)所指定的值。
public static final int value = 123;
解析:
虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化:
初始化阶段是执行类构造器(”clinit”())方法的过程。
invokevirtual指令的运行时解析:
- 找到操作数栈顶的第一个元素所指向的对象的实际类型,记做C
- 如果在类型C中找到与常量中的描述符和简单名称都相等的方法,则进行访问权限校验,如果通过则返回这个方法的直接引用,查找过程结束:如果不通过,则返回java.lang.IllegalAccessError异常。
- 否则,按照继承关系从下往上对C的各个父类进行第2步的搜索和验证过程
- 如果始终没有找到合适的方法,则抛出java.lang.AbstractMethodError异常