JVM类装载器详解

 目录

一、类装载的过程

1.1 装载(Load)

1.2 链接(Link)

1.2.1 验证(Varify)

二、类装载器组成

1. JVM 中内置了三个重要的 ClassLoader,同时按如下顺序进行加载:

2、图解

3、加载原则 所谓的双亲委派


类加载器负责在运行时将Java类动态加载到Java虚拟机,他们也是JRE(Java运行时环境)的一部分。因此,借助类加载器,JVM无需了解底层文件或文件系统即可运行Java程序。此外,这些Java类不会一次全部加载到内存中,而是在应用程序需要他们时才会进行加载,这就是类加载器发挥作用的地方,他们负责将类加载到内存中

一、类装载的过程

  类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段

Java 类的虚拟机使用 Java 方式如下:

  • Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。

  • 类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。

  • 每个这样的实例用来表示一个 Java 类。

  • 通过此实例的 newInstance()方法就可以创建出该类的一个对象。

1.1 装载(Load)

“加载”(Loading) 阶段是整个“类加载”(Class Loading) 过程中的一个阶段, 希望读者没有混淆这两个看起来很相似的名词。

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

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

加载 .class 文件的方式:

本地系统获取

网络获取,Web Applet

zip压缩包获取,jar,war

运行时计算生成,动态代理

有其他文件生成,jsp

专有数据库提取.class文件,比较少见

加密文件中获取,防止Class文件被反编译的保护措施

1.2 链接(Link)

1.2.1 验证(Varify)

验证是连接阶段的第一步, 这一阶段的目的是确保Class文件的字节流中包含的信息符合《Java虚拟机规范》 的全部约束要求, 保证这些信息被当作代码运行后不会危害虚拟机自身的安全。

从整体上看, 验证阶段大致上会完成下面四个阶段的检验动作: 文件格式验证、 元数据验证、 字节码验证和符号引用验证

文件格式验证

是否以魔数0xCAFEBABE开头。

主、次版本号是否在当前Java虚拟机接受范围之内。

常量池的常量中是否有不被支持的常量类型(检查常量tag标志) 。

指向常量的各种索引值中是否有指向不存在的常量或不符合类型的常量。

CONSTANT_Utf8_info型的常量中是否有不符合UTF-8编码的数据。

Class文件中各个部分及文件本身是否有被删除的或附加的其他信息。

元数据验证

这个类是否有父类(除了java.lang.Object之外, 所有的类都应当有父类) 。

这个类的父类是否继承了不允许被继承的类(被final修饰的类) 。

如果这个类不是抽象类, 是否实现了其父类或接口之中要求实现的所有方法。

类中的字段、 方法是否与父类产生矛盾(例如覆盖了父类的final字段, 或者出现不符合规则的方法重载, 例如方法参数都一致, 但返回值类型却不同等)

字节码验证

通过数据流分析和控制流分析,确定程序语义是合法的,符合逻辑的。

对类的方法体,进行校验分析,保证在运行时不会做出危害虚拟机的行为

保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作,不会出现类似于在操作数栈放了一个int类型的数据,使用时却按照long类型加载到本地变量表中的情况。

保障任何跳转指令都不会跳转到方法体之外的字节码指令上。

符号引用验证

通过字符串描述的全限定名是否能找到对应的类

符号引用中的类、字段、方法的可访问性是否可被当前类访问

1.2.2 准备(Prepare)

准备阶段是正式为类中定义的变量(即静态变量, 被static修饰的变量) 分配内存并设置类变量初始值的阶段。

关于准备阶段,还有两个容易产生混淆的概念笔者需要着重强调,首先是这时候进行内存分配的仅包括类变量,而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在Java堆中。

1.2.3 解析(Resolve)

解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程

事实上,解析操作往往会伴随着JVM在执行完初始化之后再执行

符号引用就是一组符号来描述引用的目标。符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中

直接引用就是直接指向目标的指针,相对偏移量或一个间接定位到目标的句柄

解析动作主要针对类,或接口,字段,类方法,接口方法,方法类型等。对应常量池中的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info

1.3 初始化(Initialization)

类的初始化阶段是类加载过程的最后一个步骤, 之前介绍的几个类加载的动作里, 除了在加载阶段用户应用程序可以通过自定义类加载器的方式局部参与外, 其余动作都完全由Java虚拟机来主导控制。 直到初始化阶段, Java虚拟机才真正开始执行类中编写的Java程序代码, 将主导权移交给应用程序

静态代码块、static 修饰的变量赋值、static final 修饰的引用类型变量赋值,会被合并成一个 <cinit> 方法,在初始化时被调用

static final 修饰的基本类型变量赋值,在链接阶段就已完成

二、类装载器组成

1. JVM 中内置了三个重要的 ClassLoader,同时按如下顺序进行加载:

  1. BootstrapClassLoader 启动类加载器:最顶层的加载类,由C++实现,负责加载 %JAVA_HOME%/lib目录下的核心jar包和类或者或被 -Xbootclasspath参数指定的路径中的所有类。

  1. ExtensionClassLoader 扩展类加载器:主要负责加载目录 %JRE_HOME%/lib/ext 目录下的jar包和类,或被 java.ext.dirs 系统变量所指定的路径下的jar包。

  1. AppClassLoader 应用程序类加载器:面向我们用户的加载器,负责加载当前应用classpath下的所有jar包和类。

除了 BootstrapClassLoader 其他类加载器均由 Java 实现且全部继承自java.lang.ClassLoader:

类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器

2、图解

3、加载原则 所谓的双亲委派

检查某个类是否已经加载:顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个Classloader已加载,就视为已加载此类,保证此类只所有ClassLoader加载一次。 加载的顺序:加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。

双亲委派机制定义:如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

双亲委派模式优势

采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。其次是考虑到安全因素,java核心api中定义类型不会被随意替换,假设通过网络传递一个名为​​java.lang.Integer​​​的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的​​java.lang.Integer​​​,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。可能你会想,如果我们在classpath路径下自定义一个名为​​java.lang.SingleInterge​​​类(该类是胡编的)呢?该类并不存在​​java.lang​​​中,经过双亲委托模式,传递到启动类加载器中,由于父类加载器路径下并没有该类,所以不会加载,将反向委托给子类加载器加载,最终会通过系统类加载器加载该类。但是这样做是不允许,因为​​java.lang​​是核心API包,需要访问权限,强制加载将会报出如下异常

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

零售数据分析模板鉴赏-品类销售结构报表

不管是服装零售&#xff0c;还是连锁超市或者其他&#xff0c;只要是零售行业就绕不过商品数据分析&#xff0c;那么商品数据分析该怎么做&#xff1f;奥威BI的零售数据分析方案早早就预设好相关报表模板&#xff0c;点击应用后&#xff0c;一键替换数据源&#xff0c;立得新报…

论文阅读:Segment Any Point Cloud Sequences by Distilling Vision Foundation Models

目录 概要 Motivation 整体架构流程 技术细节 小结 论文地址&#xff1a;[2306.09347] Segment Any Point Cloud Sequences by Distilling Vision Foundation Models (arxiv.org) 代码地址&#xff1a;GitHub - youquanl/Segment-Any-Point-Cloud: [NeurIPS23 Spotlight]…

学生用什么样的台灯比较好?分享最合适学生使用的台灯

随着现在生活水平的提高&#xff0c;越来越多人重视健康的问题。尤其是对于孩子&#xff0c;很多家长对其可谓是百般担心、千般呵护&#xff0c;害怕出现什么问题&#xff0c;其中最主要的就是近视。而如今&#xff0c;我国青少年儿童的近视率可不低的&#xff0c;达到了52.7%&…

字符与数字的相互转换

一、字符转数字 char类型字符转换为数字&#xff0c;其实是转换为ASCII码值 有两种方式&#xff1a; 1.强制类型转换&#xff0c;结果为对应的ASCII码值 char v1 a;char v2 z;char v3 1;char v4 9;int num1 (int)v1;int num2 (int)v2;int num3 (int)v3;int num4 (int)v…

如果Domino上的邮件无法直接发送到@outlook.com

大家好&#xff0c;才是真的好。 目前将Domino仅仅作为邮件服务器的企业用户还不少。如果Domino服务器版本比较新&#xff08;例如版本为11.0.x、12.0.x等&#xff09;&#xff0c;外发邮件时&#xff0c;没有通过邮件网关中转邮件&#xff0c;而是直接发送到Internet互联网上…

部署k8s dashboard(这里使用Kubepi)

9. 部署k8s dashboard&#xff08;这里使用Kubepi&#xff09; Kubepi是一个简单高效的k8s集群图形化管理工具&#xff0c;方便日常管理K8S集群&#xff0c;高效快速的查询日志定位问题的工具 部署KubePI&#xff08;随便在哪个节点部署&#xff0c;我这里在主节点部署&#…

Leetcode刷题详解——有效三角形的个数

1.题目链接&#xff1a;有效三角形的个数 2.题目描述&#xff1a; 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 示例 1: 输入: nums [2,2,3,4] 输出: 3 解释:有效的组合是: 2,3,4 (使用第一个 2) 2,3,4 (使用第二个 2) 2,2,3示…

kafka 相关概念

1 kafka 生产者 kafka 用push的方式把消息推送到topic 每个topic下可以有多个分区&#xff0c; 可以用hash 也可以用轮询的方式指定分区 每个分区内部是可以保证顺序的&#xff0c;但是整体无法保证顺序&#xff0c;除非设置成一个topic只有一个分区。 kafka这种多分区的设置 带…

在vs code中创建一个名为 “django_env“ 的虚拟环境报错?!以下方法可以解决

# vs code 终端窗口中运行&#xff1a; mkvirtualenv django_env # 拓展&#xff1a; mkvirtualenv django_env 是一个命令&#xff0c;用于创建一个名为 "django_env" 的虚拟环境。虚拟环境是一种用于隔离不同Python项目所需依赖的工具。通过创建虚拟环境&#x…

AC/DC电源模块工作效率的特点

BOSHIDA AC/DC电源模块工作效率的特点 AC/DC电源模块是一种用来将交流电转换为直流电的设备&#xff0c;在各种电子设备中应用广泛。其中&#xff0c;工作效率是评价AC/DC电源模块性能的关键指标之一。下面将从工作效率的特点方面进行阐述&#xff0c;以帮助读者更好地理解AC/…

小程序开发平台源码系统+ 带前后端完整搭建教程

大家好&#xff0c;给大家分享一个小程序开发平台源码系统。这款小程序开发平台中有很多功能&#xff0c;今天主要来给大家介绍一下洗车行业小程序制作的功能。以下是部分核心代码图&#xff1a; 系统特色功能&#xff1a; LBS定位&#xff1a;小程序能够自动显示附近的共享洗…

mysql面试题50:500台数据库,如何在最快时间之内重启

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:500台db,如何在最快时间之内重启呢? 如果需要在最快时间内重启500台数据库,可以考虑采用并行化和自动化的方法来提高效率。比如: 编写自动化脚…

Window 窗口函数 (Spark Sql)

在 Spark SQL 中&#xff0c;Window 函数是一种用于在查询结果集中执行聚合、排序和分析操作的强大工具。它允许你在查询中创建一个窗口&#xff0c;然后对窗口内的数据进行聚合计算。 import org.apache.spark.sql.expressions.Window import org.apache.spark.sql.functions…

Python+高光谱数据预处理-机器学习-深度学习-图像分类-参数回归

涵盖高光谱遥感数据处理的基础、python开发基础、机器学习和应用实践。重点解释高光谱数据处理所涉及的基本概念和理论&#xff0c;旨在帮助学员深入理解科学原理。结合Python编程工具&#xff0c;专注于解决高光谱数据读取、数据预处理、高光谱数据机器学习等技术难题&#xf…

FPGA基于1G/2.5G Ethernet PCS/PMA or SGMII实现 UDP 网络视频传输,提供工程和QT上位机源码加技术支持

目录 1、前言版本更新说明免责声明 2、我这里已有的以太网方案3、设计思路框架视频源选择OV5640摄像头配置及采集动态彩条UDP协议栈UDP视频数据组包UDP协议栈数据发送UDP协议栈数据缓冲IP地址、端口号的修改Tri Mode Ethernet MAC1G/2.5G Ethernet PCS/PMA or SGMIIQT上位机和源…

LangChain结合milvus向量数据库以及GPT3.5结合做知识库问答之一 --->milvus的docker compose安装

https://github.com/milvus-io/milvus/releaseshttps://github.com/milvus-io/milvus/releases 以下步骤均在Linux环境中进行&#xff1a; 将milvus-standalone-docker-compose.yml下载到本地。 1、新建一个目录milvus 2、将milvus-standalone-docker-compose.yml放到milvu…

【2】c++11新特性(稳定性和兼容性)—>超长整型 long long

c11标准要求long long整型可以在不同的平台上有不同的长度&#xff0c;但是至少64位&#xff0c;long long整型有两种&#xff1a; 有符号long long&#xff1a;–对应类型的数值可以使用LL或者ll后缀 long long num1 123456789LL; long long num2 123456789ll;无符号unsign…

蓝桥杯 常用STL (C++) 未完待续

动态数组 有些时候想开一个数组&#xff0c;但是却不知道应该开多大长度的数组合适&#xff0c;因为我们需要用到的数组可能会根据情况变动。 这时候我们就需要用到动态数组。所谓动态数组&#xff0c;也就是不定长数组&#xff0c;数组的长度是可以根据我们的需要动态改变的。…

innovus:antenna设置

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 innovus和ICC2还不一样&#xff0c;ICC2需要读antenna rule&#xff0c;innovus只看antenna lef&#xff0c;所以要检查一下lef里antenna信息全不全。 然后设置如下option: s…

如何优雅的实现接口统一调用

耦合问题 有些时候我们在进行接口调用的时候&#xff0c;比如说一个push推送接口&#xff0c;有可能会涉及到不同渠道的推送&#xff0c;以我目前业务场景为例&#xff0c;我做结算后端服务的&#xff0c;会与金蝶财务系统进行交互&#xff0c;那么我结算后端会涉及到多个结算…