一、验证是链接阶段(验证,准备,解析)的第一步,是验证.class文件中的二进制字节流被转换成的Java虚拟机里的Class对象是否合法的步骤。主要作用就是确保被加载的类的正确性、安全性及符合Java虚拟机规范,确保加载的.class 文件不能对虚拟机有危害。
二、验证阶段主要包括四个阶段的验证:
1.文件格式的验证:验证.class 文件字节流是否符合 文件的格式规范,并且能够被当前版本的虚拟机处理。主要包括魔数(以0xCAFEBABE开头)、主次版本号是否在虚拟机的处理范围之内、常量池中的常量是否有不被支持的类型、是否有正确的字段和方法表结构等校验。
魔数、主版本号都是.class 文件里包含的数据信息。
2.元数据验证:主要是对字节码描述的信息进行语义分析,以保证其描述的信息符合 Java 语言规范的要求,比如说验证这个类是否有父类(除了java.lang.Object),类的继承树是否合理(类是否继承了final类),类中的字段、方法是否和父类有冲突以及是否有正确的访问修饰符等。
3.字节码验证:这是整个验证过程最复杂的阶段,主要是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。例如类型转换、跳转指令、异常处理是否正确、检查字节码指令是否可能造成堆栈上出现错误类型的数据、检查局部变量在使用前是否正确初始化。在元数据验证阶段对数据类型做出验证后,这个阶段主要对类的方法做出分析,保证类的方法在运行时不会危害虚拟机。
4.符号引用验证:它是验证的最后一个阶段,发生在虚拟机将符号引用(类、接口、字段、方法)转化为直接引用的时候。主要是对类自身以外的信息进行校验,检查符号引用指向的类、接口、字段、方法是否存在并且有权限访问它们。目的是确保解析动作能够完成。
三、引申
1.若验证失败,则JVM会抛出错误(例如ClassFormatError、VerifyError),并且类加载过程会终止。
2.对整个类加载机制(加载,链接(验证,准备,解析),初始化,使用,卸载)而言,验证阶段是一个很重要但非必须的阶段,如果能够确保代码没有问题,那么就没有必要去验证,毕竟验证需要花费一定时间。
可以使用 -Xverify:none 来关闭验证。
微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。
我是程序员小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。
欢迎关注。助您在编程路上越走越好!