虚拟机类加载机制

本文详细阐述了Java类加载的时机,包括加载、链接(验证、准备和解析)、初始化过程。重点讲解了类加载器的作用,特别是双亲委派模型的工作原理。揭示了类的唯一性由加载器和全名决定,以及类加载的复杂性和灵活性。
摘要由CSDN通过智能技术生成

一、类加载时机

在这里插入图片描述

二、类加载过程

1.加载

在加载阶段,Java虚拟机需要完成一下三件事情

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

总的来说,加载阶段是将代码数据加载进内存中,是获取类的二进制字节流的动作

在在 Java 虚拟机中,类的唯一性是由类加载器实例以及类的全名一同确定的。即便是同一串字节流,经由不同的类加载器加载,也会得到两个不同的类。在大型应用中,往往借助这一特性,来运行同一个类的不同版本。

加载阶段结束后,Java虚拟机外部的二进制字节流就按照虚拟机所设定的格式存储在方法区中了,方法区中的数据存储格式完全由虚拟机自行定义。类型数据妥善安置在方法区之后,会在Java堆内存中实例化一个Class类的对象,这个对象作为程序访问方法区中的类型数据的外部接口

2.链接

验证

目的
确保Class文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身安全,规范中要求虚拟机验证到输入的字节流如不符合Class文件格式的约束,就应该抛出一个java.lang.VerifyError异常或其子类异常

文件格式验证
验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。保证输入的字节流能正确地解析并存储于方法区中,这个阶段的验证基于二进制字节流,只有通过这个阶段的验证之后,这段字节流才被允许进Java虚拟机内存的方法区中进行存储

元数据验证
对字节码描述的信息进行语义分析,保证符合《Java语言规范》的要求。

字节码验证
对类的方法体(Class文件中的Code属性)进行校验分析,保证被校验类的方法在运行时不会做出危害虚拟机安全的行为

符号引用验证
确保解析行为能正常执行,如果无法通过符号引用验证,Java虚拟机将会抛出异常

准备

目的
为被加载类的静态字段分配内存并设置类变量初始值,部分 Java 虚拟机还会在此阶段构造其他跟类层次相关的数据结构,比如说用来实现虚方法的动态绑定的方法表。

public static int value = 123;

value变量在准备阶段过后的初始值是0,把value赋值为123要到类的初始化阶段才会执行

public static final int value = 123;

当类变量被final修饰,在准备阶段将被赋值

在 class 文件被加载至 Java 虚拟机之前,这个类无法知道其他类及其方法、字段所对应的具体地址,甚至不知道自己方法、字段的地址。因此,每当需要引用这些成员时,Java 编译器会生成一个符号引用。在运行阶段,这个符号引用一般都能够无歧义地定位到具体目标上。举例来说,对于一个方法调用,编译器会生成一个包含目标方法所在类的名字、目标方法的名字、接收参数类型以及返回值类型的符号引用,来指代所要调用的方法。

解析

目的
Java虚拟机将常量池内的符号引用替换为直接引用,如果符号引用指向一个未被加载的类,或者未被加载类的字段或方法,那么解析将触发这个类的加载(但未必触发这个类的链接以及初始化)

初始化

直接赋值的静态字段被 final 所修饰,并且它的类型是基本类型或字符串时,那么该字段便会被 Java 编译器标记成常量值(ConstantValue),其初始化直接由 Java 虚拟机完成。除此之外的直接赋值操作,以及所有静态代码块中的代码,则会被 Java 编译器置于同一方法中,并把它命名为 < clinit >。初始化阶段就是执行类构造器()方法的过程,为标记为常量值的字段赋值。

Java 虚拟机会通过加锁来确保类的 < clinit > 方法仅被执行一次。

三、类加载器

1.类与类的加载器

对于任意一个类,都必须由加载他的类加载器和这个类本身一起共同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类命名空间,即比较两个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义

2.双亲委派模型

在这里插入图片描述
工作过程
如果以一个类加载器收到了类加载请求,首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的请求最终都会传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载

参考文献:深入拆解虚拟机

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值