类是如何加载的?

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 类是如何加载的?

在 Java 中,类加载的流程有一个专门的机制叫做“类加载机制”。类加载机制是指一个类在 Java 虚拟机(JVM)中的执行流程,它也是 Java 程序能够正常执行的关键所在,那它的具体执行流程是啥?接下来我们一起来看。

流程概述

在 JVM 中,类加载会经历以下 5 个阶段:

  1. 加载阶段(Loading)
  2. 验证阶段(Verification)
  3. 准备阶段(Preparation)
  4. 解析阶段(Resolution)
  5. 初始化阶段(Initialization)

其中:验证阶段、准备阶段和解析阶段合起来又称为连接阶段,所以以上 5 个阶段又可以划分为 3 大类:

  1. 加载阶段(Loading)
  2. 连接阶段(Linking)

    1. 验证阶段(Verification)
    2. 准备阶段(Preparation)
    3. 解析阶段(Resolution)
  3. 初始化阶段(Initialization)

具体分类如下图所示:
image.png
这 3 大类、5 个流程的具体执行细节是这样的。

1.加载阶段

简单来说,加载阶段就是将类文件加载到内存中的过程。在加载阶段,JVM 需要完成以下 3 件事:

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

    ## 2.连接阶段

    连接阶段又分为:验证阶段(Verification)、准备阶段(Preparation)和解析阶段(Resolution),具体执行的细节如下。

    ### 2.1 验证阶段

    验证阶段也叫做校验阶段,它主要是用来验证加载到内存中的类是否是安全合规的文件,验证的主要动作大概有以下几个(当然,以下细节如果实在记不住也没关系):

  • 文件格式校验包括常量池中的常量类型、Class 文件的各个部分是否被删除或被追加了其他信息等;
  • 元数据校验包括父类正确性校验(检查父类是否有被 final 修饰)、抽象类校验等;
  • 字节码校验,此步骤最为关键和复杂,主要用于校验程序中的语义是否合法且符合逻辑;
  • 符号引用校验,对类自身以外比如常量池中的各种符号引用的信息进行匹配性校验。

    2.2 准备阶段

    准备阶段就开始给类中的静态变量设置默认值了,注意这里不是给静态变量设置初始值,而是设置默认值,二者还是有很大区别的。
    举个例子,比如代码中写的内容是:

    public static int number = 10;

那么此时是给 number 变量设置的 int 值是默认值 0,而非初始值 10。

2.3 解析阶段

解析阶段就是将常量池中的符号引用更换成直接引用了,所谓的符号引用是指以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可;而直接引用是可以直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。
符号引用和直接引用有一个重要的区别:使用符号引用时被引用的目标不一定已经加载到内存中;而使用直接引用时,引用的目标必定已经存在虚拟机的内存中了。

3.初始化阶段

初始化阶段,Java 虚拟机真正开始执行类中编写的 Java 程序代码,将主导权移交给应用程序。到这一步骤之后,类的加载过程就算正式完成了,此时会给静态变量设置初始值,并执行静态代码块的内容。

总结

类加载流程总共分为 3 大类,5 个主要流程:

  1. 加载阶段(Loading):将类文件加载到内存。
  2. 连接阶段(Linking)

    1. 验证阶段(Verification):类文件安全性效验。
    2. 准备阶段(Preparation):给静态变量设置默认值。
    3. 解析阶段(Resolution):将符号引用转换为直接引用。
  3. 初始化阶段(Initialization):执行静态代码块和给静态变量设置初始值。
本文已收录到 Gitee 开源仓库《Java 面试指南》,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。Java 面试有它就够了,点击查看详情: interview: 400+ 道 Java 常见面试题和解析,持续更新中......
相关文章
|
6月前
|
前端开发 Java API
类加载器“如果我定义了一个类名与Java核心类类名相同,那它还能被加载吗?”
类加载器“如果我定义了一个类名与Java核心类类名相同,那它还能被加载吗?”
|
27天前
|
缓存 前端开发 JavaScript
一些有效的方法来加快网站的加载速度
【10月更文挑战第8天】一些有效的方法来加快网站的加载速度
93 62
|
6月前
|
存储 Java 程序员
【JVM】类的声明周期(加载、连接、初始化)
【JVM】类的声明周期(加载、连接、初始化)
36 1
|
存储 Java 虚拟化
JVM加载class文件的原理机制是什么?
JVM加载class文件的原理机制是什么?
|
Java 程序员
ClassLoader:类的隐式加载和显式加载
ClassLoader:类的隐式加载和显式加载
233 0
ClassLoader:类的隐式加载和显式加载
|
Java 容器 Spring
Bean的加载方式
Bean的加载方式 1.XML方式声明bean 2.XML+注解方式声明bean 3.注解方式声明配置类 扩展1——FactoryBean 扩展2——配置类中导入原始的配置文件(系统迁移) 扩展3——proxyBeanMethods 4.使用@Import导入要注入的bean 扩展4——使用@Import注解还可以导入配置类 5.使用上下文对象在容器初始化完毕后注入bean 6.导入实现了ImportSelector接口的类,实现对导入源的编程式处理 bean的加载方式(七) bean的加载方式(八)
173 1
|
PHP 开发者
类的加载(手动加载)|学习笔记
快速学习类的加载(手动加载)
类的加载(手动加载)|学习笔记
|
前端开发
一个"剑气"加载🌪️
一个"剑气"加载🌪️
|
JavaScript Java Android开发
dex加载后导入类报错
牙叔教程 简单易懂
378 0
|
Java Android开发
【Android 逆向】类加载器 ClassLoader ( 类加载时机 | 隐式加载 | 显示加载 | 类加载步骤 | 装载 | 链接 | 初始化 )
【Android 逆向】类加载器 ClassLoader ( 类加载时机 | 隐式加载 | 显示加载 | 类加载步骤 | 装载 | 链接 | 初始化 )
194 0
【Android 逆向】类加载器 ClassLoader ( 类加载时机 | 隐式加载 | 显示加载 | 类加载步骤 | 装载 | 链接 | 初始化 )