虚拟机类加载机制

简介: 类加载的过程类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。

类加载的过程

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中验证、准备、解析3个部分统称为连接(Linking),类的声明周期如下:


img_cc4e21f4a031d56a837c36f52244b702.png
image.png

虚拟机规范严格规定了有且只有以下5种情况必须立即对类进行初始化:
1)遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这4条指令的场景有:使用new关键字实例化对象、读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外),以及调用一个类的静态方法的时候。
2)使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要触发其初始化。
3)当初始化一个类的时候,如果发现其父类还没有初始化,则需要先触发其父类的初始化。
4)当虚拟机启动时,用户需要指定一个要执行的主类(包含main方法的那个类),虚拟机会先初始化这个类
5)当使用JDK1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果是REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。

加载
加载是类加载的的一个阶段。加载阶段的主要步骤:
1)通过一个类的全限定名来获取定义此类的二进制字节流(不限于本地jar包)。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
认证
认证包括以下几部分的认证:
1)文件格式验证:包括魔数、支持版本、常量类型、指向常量的索引的有效性、常量的编码等
2)元数据验证:类是否有父类、继承的合法性、非抽象类方法的完整性、方法合理性等
3)字节码验证:操作数栈语义合法性检查、虚拟机规定的类型转换校验等
4)符号引用验证:对类自身以外(常量池中的各种符号引用)的信息进行匹配性校验,包括类、方法、字段等的描述符

准备
准备阶段是正式为类变量分配内存并设置类变量(区别于实例变量,指的是类的静态字段等)初始值的阶段。比如int、short、char、float、long等类型的初始值是0,boolean类型初始值是false,reference对象类型的初始值是null。

解析
解析阶段是虚拟机将常量池内的符号引用(Class以CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info、CONSTANT_MethodType_info、CONSTANT_MethodHandle_info、CONSTANT_InvokeDynamic_info7种类符号引用结构描述)替换为直接引用(直接指向目标的指针、相对偏移量或一个能间接定位到目标的句柄)的过程。只需要保证使用的符号使用之前被解析就可以,可以先于初始化。
除了与invokedynamic指令相关的类,其他类被解析后都会被缓存,避免解析动作的重复进行。

初始化
类初始化阶段是类加载的最后一个阶段。前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的java代码。
初始化阶段是执行类构造器<clinit>()方法的过程。<clinit>()方法是由编译器自动收集所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,它不需要显示地调用父类构造器。

类加载器

对于任何一个类,都需要由加载它的类加载器和这个类本身一同确立其在java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。不同类加载器加载的同一个类不相等。

虚拟机系统提供3种的类加载器:Bootstrap ClassLoader、Extension ClassLoader、Application ClassLoader

Bootstrap ClassLoader
启动类加载器,一般由C++实现,是虚拟机的一部分。该类加载器主要职责是将JAVA_HOME路径下的\lib目录中能被虚拟机识别的类库(比如rt.jar)加载到虚拟机内存中。Java程序无法直接引用该类加载器

Extension ClassLoader
扩展类加载器,由Java实现,独立于虚拟机的外部。该类加载器主要职责将JAVA_HOME路径下的\lib\ext目录中的所有类库,开发者可直接使用扩展类加载器。 该加载器是由sun.misc.Launcher$ExtClassLoader实现。

Application ClassLoader
应用程序类加载器,该加载器是由sun.misc.Launcher$AppClassLoader实现,该类加载器负责加载用户类路径上所指定的类库。开发者可通过ClassLoader.getSystemClassLoader()方法直接获取,故又称为系统类加载器。当应用程序没有自定义类加载器时,默认采用该类加载器。

双亲委派模型
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父加载器去完成,每一个层次的类加载器都是如此。只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。

相关文章
|
存储 Java 编译器
虚拟机类加载机制
虚拟机类加载机制 一、概述 虚拟机类加载机制:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。 类的加载、连接、初始化都是在程序运行期间完成。
1445 0
|
存储 安全 Java
虚拟机类加载机制的了解
本文对java虚拟机的类加载机制进行了研究,该过程主要分为三个步骤:加载、连接、初始化,其中连接步骤可以分为:验证、准备、解析三个步骤。文中对于以上步骤进行了详细的介绍。此外,本文还涉及类加载器的部分知识:类加载器可以分为:启动类加载器、扩展类加载器、系统类加载器:java虚拟使用双亲委派的方式加载类。
1114 0
|
2月前
|
虚拟化
vmware克隆虚拟机后没有ip地址的问题
解决vmware克隆虚拟机后没有内网ip的问题
|
3月前
|
SQL 存储 数据挖掘
【虚拟机数据恢复】VMware虚拟机文件被误删除的数据恢复案例
虚拟机数据恢复环境: 某品牌R710服务器+MD3200存储,上层是ESXI虚拟机和虚拟机文件,虚拟机中存放有SQL Server数据库。 虚拟机故障: 机房非正常断电导致虚拟机无法启动。服务器管理员检查后发现虚拟机配置文件丢失,所幸xxx-flat.vmdk磁盘文件和xxx-000001-delta.vmdk快照文件还在。服务器管理员在尝试恢复虚拟机的过程中,将原虚拟机内的xxx-flat.vmdk删除后新建了一个虚拟机,并分配了精简模式的虚拟机磁盘和快照数据盘,但原虚拟机内的数据并没有恢复。
【虚拟机数据恢复】VMware虚拟机文件被误删除的数据恢复案例
|
Linux 虚拟化 数据安全/隐私保护
VMware使用 - 虚拟机克隆
如果已经安装了一台Linux操作系统,没有必要重新安装,只需要克隆就可以了,有两种方式。
23 0
|
4月前
|
存储 网络协议 虚拟化
如何操作VMware ESXi虚拟机的迁移?
如何操作VMware ESXi虚拟机的迁移?
195 1
|
4月前
|
存储 虚拟化 数据中心
如何操作VMware ESXi虚拟机的克隆?
如何操作VMware ESXi虚拟机的克隆?
86 1
|
3月前
|
Linux 虚拟化 数据安全/隐私保护
【Linux】VMware安装虚拟机- Windows + Linux
【1月更文挑战第20天】【Linux】VMware安装虚拟机- Windows + Linux
|
28天前
|
算法 虚拟化 C++
VMware虚拟机无法自适应和拖拽复制粘贴和共享目录问题
VMware虚拟机无法自适应和拖拽复制粘贴和共享目录问题
81 0
|
1月前
|
Linux 虚拟化 数据安全/隐私保护
使用VMware安装linux虚拟机
使用VMware安装linux虚拟机
使用VMware安装linux虚拟机