类的加载、连接与初始化过程的详细分析(中)

来源:互联网 发布:c语言可以用来做什么 编辑:程序博客网 时间:2024/06/07 01:10
1.类的验证

        类验证除了包装类的可用,还为了包装安全性,防止构件出自定义的类来侵入系统。

        类验证所要完成的功能:

        Ø  类文件结构的检查

             确保类文件遵从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()方法在方法区内的内存位置,这个指针就是直接引用。