类加载的过程

本文从以下方法介绍类加载过程:

一、类加载时机

二、类加载过程

一、类加载时机

       类从加载到虚拟机内存开始,到从虚拟机内存卸载出为止,生命周期如下:

       加载(Loading)

       验证(Verification)

       准备(Preparation)

       解析(Resolution)

       初始化(Initialization)

       使用(Using)

       卸载(Unloading)

注意:加载,验证,准备,初始化,卸载,5个阶段的顺序是确定的。

           验证、准备、解析阶段也称为连接阶段。

           解析阶段的顺序不一定,可能会在初始化阶段之后,这是为了支持java语言的动态绑定。

1、加载

      对于类加载过程中的第一个阶段:加载,虚拟机规范中没有明确的规定强制约束加载时机,而是有虚拟机具体实现自由把握。

2、初始化

      虚拟机规范明确规定有且只有4中情况立即对类进行初始化(而加载、验证、准备还是要在初始化之前执行)

     (1)遇到new、getstatic、putstatic、invokestatic这4条字节码指令时,如果类未初始化,则立即进行初始化。

     (2)使用java.lang.reflact包中的方法对类进行反射调用的时候,如果类未进行初始化,则需要先出发其初始化。

     (3)如果初始化一个类时,如果其父类还未进行初始化,则先初始化其父类。

    (4)当虚拟机启动时,用户指定一个执行的主类(包含main()方法的类),虚拟机会先初始化该类。

 二、类加载过程

        类加载的全过程包括加载、验证、准备、解析、初始化五个阶段。

1、加载

      “类加载”过程的第一个阶段为“加载”。

       
      加载过程虚拟机执行的操作:

      (1)通过类的全限定名(包名+类名)来获取此类的二进制字节类。

      (2)将该字节流所代表的静态存储结构转为方法区运行时数据结构。

      (3)在堆中生成一个java.lang.Class的字节码文件对象,作为访问方法区数据的入口。

  2、验证

        为连接阶段的第一步,该步骤的目的是为了确保class文件中包含的信息符合当前虚拟机的要求。

       

       (1)文件格式的验证:

                验证字节流是否符合class文件的格式规范,并且能否被当前版本的虚拟机处理。

                 该阶段的验证部分包括:

                 ①魔数;

                 ②次版本;

                 ③主版本;

                 ④常量池中的常量是否有不被支持的常量类型;

         

       (2)元数据的验证:

                对字节码的描述信息进行语义分析,确保描述信息符合java语言的规范要求。

                该阶段验证部分如下:

                ①该类是否有父类,(除了java.lang.Object之外);

                ②如果有继承关系,父类是否被final修饰;

                ③如果类不是抽象类或接口,是否实现其父类或接口中的所有方法;

                ④类中的字段、方法是否与父类产生冲突,如:重写父类中的final方法;

       (3)字节码验证

                进行数据流和流分析;对类中的方法进行校验和分析。

                ①保证任意时刻操作数栈中的数据类型与指令码序列都能配合工作;

                ②保证跳转的指令不会跳转到方法体以外的字节码指令上;

        (4)符合引用的验证

                校验虚拟机将符号引用转为直接引用的时候信息正确性,该动作在解析阶段发生。

                校验内容如下:

                ①符号引用对应的字符串所表示的全限定名是否能够找到对应的类;

                ②符号引用中的类、字段、方法的访问性(private...)是否可被当前类访问;

3、准备

      准备阶段正式为类变量(static变量)赋初始值,这些内存在方法区中分配。此阶段并未进行类变量的显示初始化赋值。

       如:private static int i =123; 该阶段初始值为0而不是123。

       特殊情况: 

              private static int i =123;     

              javac将i的值生成ConstantValue属性,则再准备阶段虚拟机会根据ConstantValue的设置将i赋值为123。

4、解析

      解析阶段虚拟机将常量池中的符号引用直接替换为直接引用的过程。

      符号引用:符号引用通过一组符号来描述目标,符号引用可以是任何形式的字面量。符号引用与虚拟机                            的内存分布无关,引用的目标不一定需要加载到内存。

      直接引用:直接指向目标的指针,相对偏移量或一个能够间接定位目标的句柄。直接引用虚拟机的内存                            布局有关,如果有直接引用,则表示目标一定在内存中。

      ①类或接口的解析

      ②字段的解析

      ③类方法的解析        

      ④接口方法的解析

5、初始化

      类加载过程中的最后一个阶段,准备阶段已经为类变量进行默认初始化赋值,则该阶段为类变量进行显示初始化赋值。

     初始化的阶段是执行类构造器<client>的过程。

     

 

 

  本文参考自 《深入理解Java虚拟机》 周志明

猜你喜欢

转载自1498116590.iteye.com/blog/2412260
今日推荐