类验证除了包装类的可用,还为了包装安全性,防止构件出自定义的类来侵入系统。
类验证所要完成的功能:
Ø 类文件结构的检查
确保类文件遵从Java类文件的固定格式
Ø 语义检查
确保类本身符合Java语言的语法规定,比如验证final类型的类有无子类,以及final类型的方法是否被覆盖或重写。
Ø 字节码验证
确保字节码流可以被Java虚拟机安全地执行。字节码流代表Java方法(包括静态和实例方法),它是由被称作操作码的单字节指令组成的序列,
每个操作码后都跟着一个或多个操作数。字节码验证步骤会检查每个操作码是否合法,即是否有着合法的操作数。
Ø 二进制兼容性的验证
确保相互引用的类之间协调一致。例如在Worker类的gotoWork()方法中会调用Car类的run()方法,此Java虚拟机验证验证Worker类的时候会
检查方法区内是否存在Car类的run()方法,如果不存(当Worker类和Car类的版本不兼容就会出现该这个问题,例如低版本JRE编译class的到高版本JRE中运行)
在就会抛出NoSuchMethodError错误。
2. 类连接之准备阶段
在准备阶段,Java虚拟机为类的静态变量分配内存空间并设置默认的初始值,注意不是程序中=赋值的哪个值,而是Java对象变量的默认值。
例如,对于以下的Simple类,在准备阶段为int类型的静态变量a分配4个字节的内存空间,并赋予默认值0;为long类型的变量b分配8个字节的内存空间,并赋予默认值0。
public class Simple {private static int a=1;
private static long b;
static { b=2;}
}
3.类连接之解析阶段
在解析阶段,Java虚拟机会把类的二进制数据中的符号引用替换为直接引用。例如Worker类中gotoWork()方法中会引用Car类的run()方法:
public void gotoWork(){
car.run(); //这段代码在Worker类的二进制数据中表示为符号引用
}
在Worker类的二进制数据中,包含了一个对Car类的run()方法的符号引用,它由run()方法的全名和相关描述符组成。在解析阶段,Java虚拟机会
把这个符号引用替换为一个指针,该指针指向Car类的run()方法在方法区内的内存位置,这个指针就是直接引用。