JVM类的加载过程

类的加载过程

类加载器的主要任务就是根据一个类的全限定名来读取此类的二进制字节流到JVM内部,然后转换为一个与目标类对应的java.lang.Class对象实例。当然类加载器所执行的加载操作仅仅是属于JVM中类加载过程中的一个阶段而已,一个完整的类加载器过程必须经历加载、连接、初始化这3个步骤。如下图所示:

                           

 

简单来说,类的加载过程就是类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区中的方法区内,这个Class对象在日后就会作为方法区中该类的各种数据的访问入口。

连接阶段要做的事就是将已经加载到JVM中的二进制字节流的类数据信息合并到JVM的运行时状态中,然而连接阶段则由验证、准备、解析三个阶段构成,其中验证阶段的主要任务就是验证类数据信息是否符合JVM规范,是否是一个有效地字节码文件。而验证的内容则涵盖了类数据信息的格式验证、语义分析、操作验证等;准备阶段的主要任务就是为类中的所有静态变量分配内存空间,并为其设置一个初始值(由于还没有实例产生,实例对象不在此范围内);而解析阶段的主要任务就是将常量池中所有的符号引用全部转换为直接引用。类加载的最后一个阶段就是初始化,在这个阶段中,JVM会将一个类中所有被static关键字标示的代码统统执行一遍,如果执行的是静态变量,那么就会使用用户指定的值覆盖掉之前在准备阶段中JVM为其设置的初始值,当然,如果程序中没有为静态变量显示指定赋值操作,那么所持有的值仍然是之前的初始值;反之如果执行的是static代码块,那么在初始化阶段中JVM就将会执行static代码块中定义的所有操作。

Java虚拟机规范在类加载和连接的时机提供了较大的灵活性,但Java虚拟机规范却明确规定了类的初始化时机,也就是说,一个类或者接口应该在首次主动使用时执行初始化操作,如下所示:

 

l  为一个类型创建一个新的对象实例时(比如new关键字,反射、序列化)

l  调用一个类型的静态方法时。

l  调用一个类型或者接口的静态字段,或者对这些静态字段执行赋值操作时,不过用final关键字修饰的静态字段除外,它被初始化一个编译时的常量表达式。

l  调用Java API中的反射方法时。

l  JVM启动包含main()方法的启动类时。

上述所列出的6中情况都属于主动使用的情形,而其他的情形则不属于主动使用,因此它们不会导致一个类型被执行初始化操作

 

一、加载字节码

加载字节码是由类加载器所负责的,当然加载操作仅仅只是类加载过程中的一个阶段,同样也是类加载过程的第一个阶段,而后续还需要连接和初始化的操作配合才能构成一个完整的类加载过程。开发人员不仅可以从一个字节码文件中读取,还能从网络中读取,甚至可以从数据库中获取出一个类的二进制字节流等。JVM并不关心数据从哪里读取,只要求所读取的字节码符合JVM规范。

 

二、验证阶段

验证阶段JVM所执行的一系列验证操作大致可以划分为:格式验证、语义分析、操作验证,以及符号引用验证等。

格式验证包括magic验证,版本验证。只有当成功通过格式验证之后,类加载器才会成功将类的二进制数据信息加载到方法区中。而后续的其他操作都在方法区中进行。接下来JVM就会开始执行下一个阶段的验证,而正式的验证操作首先会对元数据信息进行验证,而这个验证阶段的主要任务就是验证字节码信息是否符合JAVA语法规范,如下所示:

l  检查一个标记为final的类型是否包含派生类;

l  检查一个类中final方法是否被派生类进行重写;

l  确保超类与派生类之间没有不兼容的一些方法声明(比如方法签名相同,但方法的返回值不同)

 

三、准备阶段

当成功经历过验证阶段后,JVM接下来要做的事情就是对存放在方法区中类数据信息的类变量执行初始化操作,这里所执行的初始化操作并非是指类加载阶段中的初始化操作,这里仅仅只是为类中的所有静态变量分配内存空间,并为其设置一个初始值(默认值?)。比如int初始值为0,float初始值为0.0f。

 

四、解析

   解析阶段的主要任务就是将字节码常量池中的符号引用全部转换为直接引用,包括类、接口、方法和字段的符号引用。

 

五、初始化阶段

   在这个阶段,JVM将所有被static关键字修饰的代码统统执行一遍。


摘自《Java虚拟机精讲》高翔龙

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值