类加载机制详解

本文详细介绍了Java虚拟机(JVM)的类加载机制,包括加载、验证、准备、解析和初始化五个阶段。类加载器负责将Class文件加载到内存中,并进行校验、转换和初始化。加载过程涉及获取二进制字节流、转化为方法区的数据结构以及生成Class对象。验证阶段确保类文件符合规范和安全。准备阶段为类变量分配内存并设置初始值。解析阶段将符号引用转换为直接引用。初始化阶段执行类构造器<clinit>方法,对静态变量和代码块进行初始化。文章还探讨了不同场景下的类加载行为以及多线程环境下的初始化同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前在介绍JVM内存模型的时候(参看:JVM内存模型),提到了在运行时数据区之前,有个Class Loader,这个就是类加载器。用以把Class文件中的描述信息加载到内存中运行和使用。以下是《深入理解Java虚拟机第二版》对类加载器机制的定义原文:

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

一般我们把类从加载到内存到卸载出内存的整个过程分为七个阶段:加载,验证,准备,解析,初始化,使用和卸载。其中,验证、准备和解析统称为连接。

file

在这几个阶段中,加载、验证、准备、初始化和卸载这五个阶段的顺序是固定的,而解析阶段则不一定,它有时候可能会在初始化之后开始,这是为了支持Java的运行时绑定。需要特别注意的是,这里边的顺序指的是按顺序开始,而不是按顺序进行或完成,因为这些阶段通常会互相交叉的混合进行。

了解类的加载机制非常有必要,下面将逐个解释说明类加载的全过程(即加载,验证,准备,解析,初始化五个阶段)。相信看完之后,你会对Java类某些问题有更深刻的理解(例如,为什么子类可以覆盖父类的字段和方法?饿汉式单例为什么天生是线程安全的?)

加载

加载过程分为三步:

1)通过一个类的全限定名来获取定义此类的二进制字节流。

2)将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构。

3)在内存中生成一个代表这个类的Class对象,作为方法区这个类的各种数据的访问入口。

上面的第一步获取二进制字节流,并没有限定只能从编译好的.class文件中获取,也可以是zip包,jar,war,网络流(Applet),运行时计算生成(如动态代理,通过反射在运行时动态生成代理类),其他文件(如jsp,因jsp最终会编译成class),数据库(用的场景较少)。

对于数组类的加载,和普通类的加载有所不同。数组类本身不通过类加载器加载,而是由虚拟机直接完成。但是数组类的元素类型(指数组类去除维度之后的类型,如String[] 数组的元素类型就是 String)是靠类加载器加载的。

加载阶段完成之后,虚拟机就会把外部的二进制字节流(不论从何处获取的)按照一定的数据格式存储在运行时数据区中的方法区。然后在内存中实例化一个java.lang.Class对象(Class这个对象比较特殊,它存放在方法区中而不是堆中),这个对象将作为程序访问方法区中的这些数据的外部接口。

验证

验证是连接阶段的第一步,这一阶段的主要目的就是确保Class文件流中的信息符合虚拟机的规范,并且不会危害虚拟机的安全。验证阶段一般分为四个阶段:文件格式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值