类加载过程
加载模块
1.通过完全限定类获取定义该类的二进制字节流;
2.将该字节流表示的静态存储结构转换为方法区的运行时数据;
3.生成一个java。lang.Class对象,它表示类,并充当类在方法区域中的各种数据的访问点
链接到模块
验证
1.确保类文件中的字节流满足当前VM的要求,确保加载的类的正确性,并且不影响VM的安全性。
2.主要包括四种验证:文件格式验证、源数据验证、字节码验证、符号引用验证。
准备
1.为类变量分配内存,并将类变量的默认初始值设置为零。
不包括带有final的Static,因为final在编译时分配,并在准备过程中显式初始化。
类变量在方法区域中分配,而实例变量在Java堆中与对象一起分配。
解析
1.将常量池中的符号引用转换为直接引用的过程。
2.实际上,解析操作是在初始化后用JVM执行的
3.符号参照是描述被参照对象的一组符号。符号应用程序的文字形式在Java虚拟机规范的类文件格式中有明确定义。直接引用是直接指向目标的指针、相对偏移量或间接指向目标的句柄
4.解析操作主要针对类或接口、字段、类方法、接口方法和方法类型。常量池中的常量类信息、常量字段参考信息和常量方法参考信息。
初始化模块
1.Clinit()是类或接口初始化方法。请注意,它不是构造函数init()。
2.这个方法不需要定义,它是静态代码块中的语句和Java编译器为类中的所有类变量自动收集的赋值操作的组合。
3.我们注意到,如果没有静态变量C,字节码文件中就不会有Clinit方法
构造函数方法Clinit()中的指令按照语句在源文件中出现的顺序执行
虚拟机必须确保一个类的Clinit()方法在多个线程中同步锁定,这意味着一个类在其内部信息存储到方法区域之前只需要Clinit一次。