虚拟机类加载机制

Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称为虚拟机的类加载机制。

与哪些在编译时需要进行连接的语言不同,在Java语言里,类型的加载、连接和初始化过程都是在程序运行期间完成的,这种策略让Java语言进行提前编译会面临额外的苦难,也会让类加载时稍微增加一些性能开销,但却为Java应用提供了极高的扩展性和灵活性,Java天生支持动态扩展的特性就是依赖运行期动态加载和动态连接的特点实现的。

Class文件:一串二进制字节流,无论已何种形式存在,包括不限于磁盘文件、网络、数据库、内存或动态产生等。

类加载时机

一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading),七个阶段。其中验证、准备、解析三部分统称为连接(Linking)。

lifecycle-of-a-class

加载

加载阶段需完成三件事:

  1. 通过一个类的全新定名来获取定义此类的二进制字节流
  2. 将这个字节流所代表的静态存储结构转化为方法区的进行时数据结构
  3. 在内存中生成一个代表该类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

验证

验证是连接阶段的第一步,目的是确保Class文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机的自身安全。

准备

准备阶段是正式为类中定义的变量(静态变量)分配内存并设置类变量初始值的阶段,从概念上讲,这些变量所使用的内存都应当在方法区中进行分配,但需要注意的是方法区本身是一个逻辑上的区域。从JDK7及之后,类变量则会随着Class对象一起存放在Java堆中。

该阶段仅为类变量分配内存空间,而不包括实例变量。

public static int value = 123;

value在准备阶段时设置的初始值为0,而不是123,因为此时尚未执行任何Java方法,而把value赋值为123的putsstatic指令是程序编译后,存放于类构造器<init>

()方法之中,所以设置value的动作要到类的初始化阶段才能被执行。

也有例外

public static final int value = 123;

如果类字段的字段属性表中存在ConstantValue属性,那么准备阶段变量值就会被设置为ConstantValue属性所指定的初始值。

解析

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

符号引用:以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义的定位到目标即可。

直接引用:可以直接指向目标的指针、相对偏移量、或是一个能间接定位目标的句柄。

初始化

类的初始化是类加载过程的最后一步,知道初始化阶段,Java虚拟机才真正开始执行类中编写的Java程序代码。

进行准备阶段时,变量已经赋过一次系统要求的初始零值,而在初始化阶段,则会根据程序员通过程序编码制定的主观计划去初始化类变量和其他资源。

 

posted @ 2025-12-17 12:25  wang_longan  阅读(5)  评论(0)    收藏  举报