当前位置: 首页 > news >正文

5. 类加载子系统

在这里插入图片描述

一、前言

前面我们了解了字节码文件的大致组成部分,那么 JVM 是如何加载 .class字节码文件的?加载到.class字节码文件后又做了哪些事情呢?

二、类加载子系统初步认识

首先类加载子系统作为虚拟机和外界的一个对接口,主要负责以下几点:

  • 负责从文件或者网络加载 Class 字节流
  • 读取字节码中的信息,存入 JVM 内存中 (方法区)
  • 对字节流进行规范化校验

三、类加载器子系统加载过程

如下图中所示,.class文件最先由类加载器子系统进行处理,而类加载器子系统进行一个类的加载的时候内部大致可分为三个阶段,加载阶段 -> 链接阶段 -> 初始化阶段。见下图

3.1 加载阶段 Loading

这里我就不摘抄书中内容了,用比较通俗的语言描述,这里加载其实就是读取字节流内容到内存中,通过类的全限定名来进行定位,读取到内容后,将所有的静态结构转化为运行时数据结构,然后存储的方法区中,然后生成一个这个类的 java.lang.Class 对象,放入中,作为在方法区中这个类的访问入口。注意这个阶段只负责读和存,不做任何验证处理。加载的过程中,必然会触发父类的加载。

补充说明:Class 实例是如何被创建的。

  • new 实例化
    • A a = new A();
  • 反射
    • Class clzA = Class.forName("com.xxx.xxx.A");
  • 子类加载时作为父类同时加载
  • JVM 启动时,包含 main 方法的主类
  • 1.7 的动态类型语言支持

3.2 链接阶段

  • 验证 Verify
    • 文件格式验证:验证魔数、版本、常量池这些格式相关的数据
    • 元数据验证:这个类是否有父类,以及这个类的父类是不是被 final 修饰,不允许被继承等。主要针对元数据语义方面的校验
    • 字节码校验:这个阶段最为复杂,主要通过数据流分析和控制流分析,确定语义合法,符合逻辑。针对类的方法体(Class 文件中的 Code 属性)进行校验分析,保证方法运行时不出现危害虚拟机安全的行为。
    • 符号引用验证:这个在整个链接阶段中的最后一个阶段,解析阶段中将符号引用转化为直接引用时发生,比如:全限定类名是否能找到该类。

验证和加载并不是线性的关系,并不是先将流信息全部加载完,再去逐行验证,而是交替进行,可以理解为一边读一边校验。注意这里验证的只是针对流文件的内容,静态数据校验,与运行时环境无关,所以目标 Class 对象不一定已经被加载到内存中,符号引用是由字节码规定的。

验证阶段非常重要,但是没必要每次都进行验证,只要通过了之后对程序运行期没有任何影响了。如果程序运行全部代码都已经反复使用和验证过,生成环境的实施阶段可以考虑使用 -Verify:none 参数来关闭大部分类验证措施,以缩短虚拟机类的加载时间。

  • 准备 Prepare
    • 为类中定义的变量分配内存并设置类变量初始值(注意:这里指类变量,static修饰的变量),这里的初始值 “通常情况” 下是数据类型的零值,比如 public static int value = 123;, 那么准备阶段初始值为 0而不是 123。参考下表。
  • **解析 Resolve **
    • 解析是将常量池内的符号引用替换为直接引用的过程,符号引用:一些字面量;直接引用:可以直接指向目标的指针、相对偏移量或者是间接定位到目标的句柄。
    • 类\接口解析、字段解析、方法解析、接口方法解析

3.3 初始化阶段

执行类构造器 <clinit>()方法。此方法是执行过程中,由编译器自动收集类中的所有变量的赋值动作静态代码块static{}块)中的语句合并产生的。编译器收集的顺序是语句在源文件中出现的顺序决定的,所以静态代码块中只能访问到定义在之前的变量,定义在后面的变量,只能进行赋值,不能访问。

执行过程的本质:

  • 对静态变量赋值以及执行静态代码块
  • 子类初始化过程会优先执行父类的 <clinit>()
  • 没有静态变量及静态代码块(static{}) 就不会产生 <clinit>()
  • 设置启动参数-XX: +TraceClassLoading查看类加载过程
  • <clinit>()方法会默认增加同步索确保只执行一次

四、总结


http://www.mrgr.cn/news/70427.html

相关文章:

  • 28.UE5游戏框架,事件分发器,蓝图接口
  • SCP文件传输命令解析
  • 全面解析多种mfc140u.dll丢失的解决方法,五种方法详细解决
  • Intern大模型训练营(十):评测 InternLM-1.8B 实践
  • HarmonyOS NEXT技术分享
  • windows实现VNC连接ubuntu22.04服务器
  • 多模态融合-决策层融合
  • Git - 命令杂谈 - fetch与push
  • 如何在本地文件系统中预览 Vue 项目?
  • AVL 树的模拟实现(入门必看,图文并茂)
  • linux 下调试 mpu6050 三轴加速度
  • 某《财富》世界500强制造企业基于大模型实现财税智能问数
  • OmniGen: Unified Image Generation(代码的学习)
  • 前端常用时间操作汇总
  • 二分查找题目:x 的平方根
  • [分享]分享一下我用了十几年的按键扫描方法
  • 北京大学、华为公司联合发布《中国城市治理数字化转型报告(2024)》49页PDF附下载
  • 谷歌Linux内核自动测试平台架构介绍-用自动测试测试难以测试的问题
  • 【RabbitMQ】06-消费者的可靠性
  • 【前端】手写一个简单的分页器
  • 如何解决亚马逊商家IP问题:静态住宅IP的优势与选择指南
  • 1547. 切棍子的最小成本-cangjie
  • 网络、子网
  • 实验室信息管理系统源码,医院LIS系统源码,C/S结构,C#语言开发,适合上项目。
  • vxe-vxe-colgroup后端返回数据 对数据进行处理 动态合并分组表头(v-if控制表格渲染(数据请求完成后渲染))
  • ROS2在自定义服务接口中的常数调用(python)