Java虚拟机:加载、链接与初始化

时间:2021-06-26 19:45:04

加载是根据特定名称查找类或接口类型的二进制表示,并由此二进制表示来创建类或接口的过程。
链接是为了让类或接口可以被Java虚拟机执行,而将列或接口并入虚拟机运行时状态的过程。
类或接口的初始化是指执行类或接口的初始化方法。

在做一系列的动作之前,首先得把Java虚拟机启动吧,咱们先来说下Java虚拟机的启动过程:Java虚拟机的启动是通过引导类加载器创建一个初始类来完成的,这个类是由虚拟机的具体实现指定的。紧接着,Java虚拟机链接这个初始类,初始化它并调用它的public方法void main(String[])。之后的整个执行过程都是由对此方法的调用开始的。

加载

    当程序需要使用某一个类时,如果该类还没有加载到内存中,Java虚拟机就会通过加载、链接和初始化三个步骤来对该类进行初始化,将类加载到内存中,供使用。

    类的加载是将类的class文件加载读入内存,并为之创建一个java.lang.Class对象(每个加载的类都有一个唯一对应的Class对象)。

    类的加载由类加载器完成,常见的三个类加载器有Bootstrap ClassLoader、Extension ClassLoader、System ClassLoader。加载器的级别从高到低。

通过使用不同的类加载器,可以加载不同来源的类的二进制数据,常见的数据来源有:

  • 本地文件系统加载class文件;
  • 通过网络加载class文件;
  • 通过jar包夹杂class文件;
  • 通过用户自定义的类生成的class文件;

链接

当类被加载后,系统会为之生成一个对应的Class对象,接着就会进入类的链接阶段。
链接类或接口包括验证和准备类或接口、它的直接父类、它的直接父类接口、它的元素类型。

类的链接阶段负责把类的二进制数据合并到JRE中。类的链接又可以分为如下三个阶段:

  • 验证:验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致;
  • 准备:类的准备阶段则负责为类的静态属性分配内存,并设置默认初始值;
  • 解析:将类的二进制数据中的符号引用替换成直接引用。

初始化

在类的初始化阶段,虚拟机负责对类进行初始化,主要是对静态属性进行初始化。在java类中对静态属性进行初始化有两种方式:

  • 声明静态属性时指定初始值;
  • 使用静态初始化块为静态属性指定初始值。

JVM对类进行初始化时包含如下步骤:

  • 假如这个类还没有被加载和链接,程序先执行加载并连接这个类;
  • 假如该类的直接父类还没有被初始化,则先初始化其直接父类;
  • 假如类中有初始化语句,则系统依次执行这些初始化语句。

根据如上步骤可以看出来,当程序主动使用任何一个类时,系统会保证该类以及所有父类都会被初始化。

类初始化的时间

系统开始初始化类或接口的时间包括一下6种情况:

  • 创建类的实例;
  • 调用某个类的静态方法;
  • 访问某个类或接口的静态属性,或为该静态属性赋值;
  • 通过反射方式来创建某个类或接口对应的java.lang.Class对象,如使用Class.forName(“Person”);
  • 初始化某个类的子类。初始化子类时,所有的父类都会被初始化;
  • 直接使用java命令来运行某个类时。