Java虚拟机——类加载的过程

news2024/10/5 10:22:15
  • 接下来,我们会详细了解Java虚拟中类加载的全过程。
  • 即加载、验证、准备、解析和初始化这五个阶段所执行的具体动作。

加载

  • 在加载阶段下,Java虚拟机需要完成三件事
  1. 通过一个类的全限定名来获取定义此类的二进制字节流
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问的入口。
  • *对这三点的要求不是很具体,所以虚拟机实现的灵活度很大。
    在这里插入图片描述
  • 加载阶段可以使用虚拟机里内置的启动类加载器来完成,也可以由用户自定义的类加载器去完成。
  • 开发人员可以通过定义自己的类加载器去控制字节流的获取方式。

- 对于数组类来说

  • 数组类本身不通过类加载器创建,它是由Java虚拟机直接在内存中动态构造出来。
    请添加图片描述
  • 加载结束之后,Java虚拟机外部的二进制字节流就按照虚拟机设定的格式存储在方法区之中。
  • 同时会在Java堆内存中实例化一个java.lang.Class类的对象,这个对象将作为外部访问方法区中的类型数据的外部接口。

加载阶段与连接阶段的部分动作是交叉进行的。

验证

  • 验证是连接的第一步,这一阶段的目的就是 确保Class文件的字节流包含的信息符合*的全部约束要求。保证这些信息被当作代码运行后不会危害虚拟机自身的安全。
  • 必要性:虽然Java语言是相对安全的,但是Class文件不一定只能由Java源码编译而来,它可以有很多途径产生。所以为了防止载入有错误或有恶意企图的字节码流而导致整个系统受攻击甚至崩溃,是由必要的措施。
  • 验证阶段大致完成了下面四个阶段的检验动作。
    在这里插入图片描述
  1. 文件格式验证
  • 验证字节流是否符合Class文件格式的规范,并且能够被当前版本的虚拟机处理。
  • 目的:保证输入的字节流能够正确解析并存储于方法区之内,格式上符合描述一个Java类型信息的要求。
  • 这阶段的验证是基于二进制字节流进行的,只有通过这阶段的验证之后,字节流才被允许进入Java虚拟机内存的方法去中进行存储。
  1. 元数据验证
  • 对字节码描述的信息进行语义分析,以保证其描述的信息符合*的要求。
  • 目的:对类的元数据信息进行语义校验
  1. 字节码验证
  • 目的:通过数据流分析和控制流分析,确定程序语义是合法的、符合逻辑的。
  • 在第二阶段对元数据信息中的数据类型进行校验完毕以后,这阶段就要对类的方法体(Class文件中的Code属性)进行校验分析,保证被验证类的方法在运行时不会做出危害虚拟机安全的行为。
  • 当然就算通过了字节码验证,也不代表代码一定是安全的。不可能用程序来准确判定另一段程序是否存在bug。
  1. 符号引用验证
  • 虚拟机将符号引用转化为直接引用的时候。 这个转化动作将发生在连接的第三阶段-解析中。
  • 符号引用可以看成是对类自身以外的各类信息进行匹配性校验。就是查看该类是否缺少或者被禁止访问他依赖的某写外部类、方法、字段等资源。
  • 目的:确保解析行为能够正常执行。

准备

  • 准备阶段是正式为类中定义的变量(即静态变量、被static修饰的变量)分配内存并设置类变量初始值的阶段
  1. JDK 7 之后,类变量会随着Class对象一起存放在Java堆中
  2. 这时候进行内存分配的仅包括类变量,而不包括实例变量。实例变量会随着对象实例化时随着对象一起分配在Java堆中。
  3. 其次是这里的初始值指的是数据类型的零值。
  4. 把value赋值成123的putstatic指令是程序编译后,存放于类构造器()方法之中,所以要到类的初始化阶段才会执行。
public static int value = 123;
  1. 如果类的字段表中存在ConstantValue属性,那么在准备阶段变量值就会被初始化为ConstantValue属性所指定的初始值。
public static final int value = 123;

解析

  • 解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程
    在这里插入图片描述
  • 上面代码中,Test类中引用了MyObject类和它的method方法。
  • 在编译期,Java编译器将Test类中对MyObject类和method方法的引用转化为符号引用,并保存在字节码文件中。
  • 在运行期,当编译器需要访问MyObject类和method方法时,它将符号引用转化为直接引用,即指向内存地址的指针。
public class Test {
  public static void main(String[] args) {
    MyObject obj = new MyObject();
    obj.method();
  }
}

class MyObject {
  public void method() {
    System.out.println("Hello, world!");
  }
}

  • *并没有规定解析阶段的具体发生时间,只要求在17个用于操作符号引用的字节码指令之前,先对他们所使用的符号引用进行解析。
  • 所以,虚拟机实现可以根据需要来自行判断,到底是在类被加载器加载时就对常量池中的常量进行解析,还是等到一个符号引用要被它使用时前才去解析它。

能不能对同一个符号引用进行多次解析?

  • 对同一个符号引用进行多次解析请求是很常见的事情。
  • 虚拟机会对第一次解析的结果进行缓存,譬如在运行时直接引用常量池中的记录,并把常量标识为已解析状态,从而避免解析动作的重复进行。
  • 一个符号引用如果已经被成功解析过,那么后续的引用解析请求就应当一直能够成功。反之。

具体引用的解析过程

  • 解析动作主要是针对类、接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符这7类符号引用。

1. 类或接口的解析

  • 假设当前代码所处的类为D,如果要把一个从未解析过的符号引用N解析为一个类或接口C的直接引用,那么虚拟机完成整个解析过程需要包括以下3个步骤。
    在这里插入图片描述

2. 字段解析

  • 在解析字段之前,首先会将字段所属的类或接口的符号引用进行解析。如果解析成功了,那把这个字段所属的类后接口用C表示,接下来按照以下步骤对C进行后续的字段搜索。
    在这里插入图片描述

3. 方法解析

  • 方法解析的第一个步骤与字段解析一样,也是需要先解析出方法所属的类或接口的引用。如果解析成功,依然用C表示这个类。

4. 接口方法解析

  • 同理

初始化

  • 类的初始化是类加载过程的最后一个步骤,之前的几个类加载动作中。

  • 除了在加载阶段,用户应用程序可以通过自定义类加载器的方式参与外,其余的动作都是完全由Java虚拟机来主导。

  • 直到初始化阶段,Java虚拟机才真正开始执行类中的编写的Java程序代码,将主导权移交给应用程序。

  • 准备阶段的时候,变量已经赋过一次系统要求的初始零值。而在初始化阶段,会根据程序员通过程序编码指定的主观计划去初始化类变量和其他资源
    在这里插入图片描述

  1. 静态语句块只能访问到定义在静态语句块前的变量。 定义在后面的变量,可以赋值但是不能访问。
public class ClintStaticTest {
    static {
        i = 0;
        System.out.println(i);//提示非法前向引用
    }
    static int i = 1;
}
  1. ()方法保证在子类的该方法执行前,父类的()方法一定已经执行完毕,所以Java虚拟机中第一个被执行的一定是java.lang.Object
  2. 父类的静态语句块一定优先于子类的变量赋值操作。
public class Parent {
    public static int A = 1;
    static {
        A = 2;
    }
}


public class Sub extends Parent{
    public static int B = A;
}

public static void main(String[] args) {
     System.out.println(Sub.B)}
  1. ()方法不是必须的,如果没有赋值操作,也没有静态语句块就不需要。
  2. 接口中可以赋值,所以也有该方法。 接口不需要先执行父接口的方法,因为只有父接口中定义的变量被使用时,父接口才会被初始化。
  3. 一个类的()方法需要在多线程环境中被正确地加锁同步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/769128.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Small Tip: 怎么找S4HANA所有的CDS View

1. SAP Business Accelerator Hub 到网址:https://api.sap.com 2. 到Categories底下找。如果没看见CDS View就去View all categories 3. 找到CDS Views之后,点击进去。 4. 按Package 分类来找:

实时网络更改检测

未经授权的配置更改可能会对业务连续性造成严重破坏,这就是为什么使用实时更改检测来检测和跟踪更改是网络管理员的一项关键任务。尽管可以手动跟踪更改,但此方法往往非常耗时,并且通常会导致人为错误,例如在跟踪时错过关键网络设…

Spring Boot : ORM 框架 JPA 与连接池 Hikari

数据库方面我们选用 Mysql , Spring Boot 提供了直接使用 JDBC 的方式连接数据库,毕竟使用 JDBC 并不是很方便,需要我们自己写更多的代码才能使用,一般而言在 Spring Boot 中我们常用的 ORM 框架有 JPA 和 Mybaties ,本…

C#的ref和out使用

ref和out是C#中用于参数传递的关键字,它们都允许在方法内部修改参数的值,区别如下: 1、ref关键字:使用ref关键字声明的参数,在方法调用前必须被初始化,并且可以被视为已经赋予了一个初始值。在方法内部对r…

会议OA项目之会议发布(多功能下拉框的详解)

🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于OA项目的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 一.主要功能点介绍 二.效果展示 三.前…

【网络编程】传输层协议——TCP协议

文章目录 一、TCP协议格式1.1 TCP如何将报头与有效载荷进行分离?1.2 有效载荷如何向上交付?1.3 TCP报头的理解1.4 序号与确认序号1.4.1 网络不可靠问题1.4.2 32位序号1.4.2 32位确认序号 1.5 窗口大小1.6 六个标志位 二、确认应答机制(ACK&am…

集成学习Bagging——随机森林模型

目录 1. Bagging方法的基本思想 2. 随机森林RandomForest 2.1 RandomForestRegressor的实现 2.2 随机森林回归器的参数 2.2.1 弱分类器结构 2.2.2 弱分类器数量 2.2.3 弱分类器训练的数据 2.2.4 其它参数 1. Bagging方法的基本思想 Bagging又称“袋装法”,它…

keyclaok~keycloak存到cookie中的值和session_state

keycloak存到cookie中的值 AUTH_SESSION_IDKEYCLOAK_IDENTITYKEYCLOAK_SESSION AUTH_SESSION_ID 用户的当前session_state,它是会话级的,关闭浏览器就没了 KEYCLOAK_IDENTITY 它是用户跨端登录的基础,它也是一个jwt串,解析后…

Scala学习(三)

2.8 浮点类型(Float、Double) Scala的浮点类型可以表示一个小数,比如123.4f,7.8,0.12等等。 1)浮点型分类 数据类型 描述 Float [4] 32 位, IEEE 754标准的单精度浮点数 Double [8] 64 位 IEEE 754标准的双…

electron+vue3全家桶+vite项目搭建【24】设置应用图标,打包文件的图标

文章目录 引入实现步骤测试结果 引入 在electron中,我们可以通过electron-builder的配置文件来设置打包后的应用图标 实现步骤 因为mac环境下的图标需要特殊格式,这里我们可以利用electron-icon-builder进行配置 1.引入相关依赖 # 安装electron-ico…

Halcon 深度学习初探

什么是深度学习? 深度学习是一系列机器学习的方法集合,其算法结构类似于多层级的神经网络。通过对大量的训练样本图像的学习,提取其各个层次的特征,使网络具有判别和推理能力。 关于halcon中的深度学习: 自halcon17…

C#中的HashTable和Dictionary之间的区别

面试基础:C#中的HashTable和Dictionary之间的区别 HashTable和Dictionary都是用于存储数据的数据结构的类型。这两个数据结构都将存储的数据保存为键值对。

ESP32 VS Code开发环境“hello world“

程序员的世界有个不成文的约定,第一个程序先跑"hello world",今天我们就在esp32上跑下hello world! vs code配置 新建一个esp32-test文件夹,并在该文件夹下打开vs code: mkdir esp32-test cd est32-test …

小白到运维工程师的自学之路 第五十四集 (ansible自动化运维工具)

一、概述 Ansible是一种开源的自动化工具,用于自动化任务的执行、配置管理和应用部署。它采用基于Python编写的简单、轻量级的语法,可以通过SSH协议远程管理和配置多台计算机。 Ansible的主要特点包括: 1、简单易用:设计简单&a…

自动驾驶多任务框架 MultiTask V3、HybridNets和YOLOP比较

目标检测和分割是自动驾驶汽车感知系统的两个核心模块。它们应该具有高效率和低延迟,同时降低计算复杂性。目前,最常用的算法是基于深度神经网络的,这保证了高效率,但需要高性能的计算平台。 在自动驾驶汽车的场景下,大多使用的都是计算能力有限的嵌入式平台,这使得难以满…

Python 算法基础篇之散列查找算法:哈希表、哈希集合、哈希映射

Python 算法基础篇之散列查找算法:哈希表、哈希集合、哈希映射 引言 1. 散列查找算法概述2. 哈希表的概念3. 哈希集合的概念4. 哈希映射的概念5. 实例演示实例1:哈希表实例2:哈希集合实例3:哈希映射 总结 引言 散列查找算法是一种…

Spring Cloud 之 Gateway 网关

🍓 简介:java系列技术分享(👉持续更新中…🔥) 🍓 初衷:一起学习、一起进步、坚持不懈 🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏 🍓 希望这篇文章对你有所帮助,欢…

Web安全基础

Web安全基础 一、Web应用安全概述1.1、什么是Web应用安全?1.2、WEB应用安全的兴起1.3、常见web应用1.3.1、常见Web应用—前后台 1.4、Web应用安全与传统安全的区别 二、Web应用的基本架构2.1、Web应用的基本架构2.2、Web服务的提供者——Web中间件2.3、简单的Web服务…

javascript实现久久乘法口诀表、document、write、console、log

文章目录 正序乘法口诀表倒序乘法口诀表logconsoledocumentwrite 正序乘法口诀表 function multiplicationTable() {for (let i 1; i < 9; i) {let val ;for (let j 1; j < i; j) {document.write(j * i (i * j) &nbsp );val ${j}*${i}${i * j} ;}consol…

肯尼亚税务局如何利用RPA、AI等创新技术来推动税务合规增加税收?

在当今的数字化时代&#xff0c;税务部门的工作变得日益复杂。依赖手动程序为税务部门带来了巨大的困难&#xff0c;这使得在有效管理税收和实现收入目标上遇到了阻碍。手动流程往往效率低下&#xff0c;易出错&#xff0c;而且难以应对大规模的数据处理需求。如果不能解决该问…