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.mzph.cn/news/107040.shtml

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

相关文章

多关键词高亮显示

引入关键词文件&#xff0c;符合有条件的背景色高亮显示&#xff0c;也可取消。 <div id"testHtml"><p>写入的文本</p><p>关键词</p></div> var str 多个关键词&#xff0c;关键词文件&#xff0c;关键词 var strL str.replac…

nginx报错

故障1&#xff1a;nginx 502错误 故障描述 一个 post 的请求&#xff0c;直接调接口服务数据正常返回&#xff0c;但是通过 nginx 代理后&#xff0c; 什么都没有返回 nginx错误日志 upstream sent invalid chunked response while reading upstream 原因 http协议版本不一致…

【C++】C++11—— 包装器

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;C学习 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【C】C11…

2023年中国TFT-LCD面板产业链、需求量及市场规模分析[图]

按显示技术尺寸来分&#xff0c;主要分为大尺寸和小尺寸&#xff08;10寸以下&#xff09;&#xff0c;TFT-LCD行业下游主要是各类型消费电子&#xff0c;包括PC显示器&#xff0c;液晶电视&#xff0c;智能手机等。 TFT&#xff0d;LCD面板产业链 资料来源&#xff1a;共研产…

【广州华锐互动】利用VR开展细胞基础实验教学有什么好处?

在科技发展的驱动下&#xff0c;虚拟现实&#xff08;VR&#xff09;技术已被广泛应用于各个领域&#xff0c;包括教育和医学。尤其是在医学教育中&#xff0c;VR技术已成为一种革新传统教学模式的有效工具。本文将探讨使用VR进行细胞基础实验教学的优势。 首先&#xff0c;VR技…

(SCADA)监控与数据采集系统

SCADA应用于监控和采集数据来控制工业过程软件。它通过收集和传输实时数据&#xff0c;帮助操作员监视和控制各种设备和过程。这篇文章将介绍SCADA系统的工作原理、应用行业和场景&#xff0c;以及所需的模块和硬件设备。最后&#xff0c;还会详细介绍几款国外SCADA软件给大家参…

VUE整合Echarts实现简单的数据可视化

文章目录 前言 一、Echarts的安装 二、可视化渲染 1.柱状图 2.饼图 3.主题的下载 总结 前言 ECharts是一款功能强大的前端数据可视化库&#xff0c;支持多种图表类型和统计图表、地理数据可视化、关系型数据展示、多维数据处理和商业智能功能。通过广泛的图表类型、统计分析…

FPGA面试题(5)

一.FPGA可以综合实现为RAM/ROM/CAM的三种资源及注意事项 三种资源&#xff1a;BLOCK RAM&#xff0c;触发器&#xff08;FF&#xff09;&#xff0c;查找表&#xff08;LUT&#xff09; 注意事项&#xff1a; 1.生成RAM&#xff0c;首选BLOCK RAM。因为BLOCK RAM是已经存在的“…

Springboot项目中加载Groovy脚本并调用其内部方代码实现

前言 项目中部署到多个煤矿的上&#xff0c;每一种煤矿的情况都相同&#xff0c;涉及到支架的算法得写好几套&#xff0c;于是想到用脚本实现差异变化多的算法&#xff01;一开始想到用java调用js脚本去实现&#xff0c;因为这个不需要引入格外的包&#xff0c;js对我来说也没…

测试需要写测试用例吗?

如何理解软件的质量 我们都知道&#xff0c;一个软件从无到有要经过需求设计、编码实现、测试验证、部署发布这四个主要环节。 需求来源于用户反馈、市场调研或者商业判断。意指在市场行为中&#xff0c;部分人群存在某些诉求或痛点&#xff0c;只要想办法满足这些人群的诉求…

docker部署多个node-red操作过程

docker部署多个node-red操作过程 一、docker安装教程二、docker安装node-red2.1 拉取镜像2.2 创建目录并分配权限 三、 docker操作node-red3.1 部署node-red3.2 查看\关闭\删除容器 四、Docker删除Redis镜像 回到目录 一、docker安装教程 【docker使用安装教程】 回到目录 …

NI GPIB-140A 使用缓冲传输技术 边缘人工智能

NI GPIB-140A 使用缓冲传输技术 边缘人工智能 GPIB总线扩展器—GPI b-140 a可以将GPIB系统的电缆长度延长一千米&#xff0c;而不会影响GPIB的完整性&#xff0c;也不需要修改软件。该配件使用缓冲传输技术&#xff0c;以高达1.1 Mb/s (IEEE 488.1)或2.8 Mb/s (HS488)的速率传…

安科瑞预付费系统在某大型连锁农贸市场的设计应用

安科瑞 崔丽洁 摘要 本远程预付费管理系统采用智能远程预付费电表&#xff08;DTSY1352-NK/DDSY1352-NK系列&#xff09;&#xff0c;NB智能远传水表&#xff0c;采集各商户实时用电量、用电量总数&#xff0c;通过平台定时结算&#xff0c;结算账户余额&#xff0c;从而进行智…

4d动感影院座椅5d动感影院体验馆大型7D互动影院

今天来讲一下市场上现在受欢迎的5d7d影院&#xff0c;组成部分&#xff0c;落地方案 5D影院的系统组成部分&#xff1a;1、动感座椅、2、投影幕(银幕)和投影机、3、音箱、4、各种的动感特效、5、5d影院眼镜&#xff0c;很简单的组成硬件&#xff0c;就可以组成一套的5d影院设备…

专题三:穷举、暴搜、深搜、回溯、剪枝【递归、搜索、回溯】

1、全排列 class Solution { public:vector<vector<int>> ret;vector<int> path;bool check[7];void dfs(vector<int>& nums){if(nums.size() path.size()) {ret.push_back(path);return;}for(int i 0;i < nums.size();i){if(check[i] fals…

HBase基础

HBase基础 参考 https://www.bilibili.com/video/BV1bC4y1b7Q1 HBase 简介 定义 HBase是一种分布式、可扩展、支持海量数据存储的NoSQL数据库(k-v)。 数据量越大&#xff0c;优势越明显&#xff1b;数据量小&#xff0c;比较消耗内存&#xff0c;耗资源&#xff1b;数据量大…

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

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

无线通信——Mesh体系结构

Mesh体系结构 了解Mesh的体系结构有利于我们后期的理解&#xff01;这里有些简单的知识点以及解释 WMN&#xff1a;WMN就是无线mesh网络&#xff0c;我们一般提到WMN其实特指就是Mesh网络的整个体系结构 STA&#xff1a;客户工作站&#xff0c;这个东西就是用户的设备端&…

《软件方法》2023版第1章(09)基本共识上的沟通,SysML

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 1.3 UML 1.3.2 使用UML的理由 1.3.2.5 基本共识上的沟通 符号标准并不是随便哪个人拍脑袋定下来&#xff0c;然后毫无道理地强迫大家接受。符号背后往往隐含着我们对某个学科的一些…

SpringAOP是什么?为什么要有SpringAOP?

SpringAOP是什么&#xff1f;为什么要有SpringAOP&#xff1f; 原文&#xff1a;SpringAOP是什么&#xff1f;为什么要有SpringAOP&#xff1f; 一、有SpringAOP之前 简单的开发场景&#xff0c;只需要写简单的业务逻辑&#xff0c;比如CRUD 但是在执行具体的逻辑之前&…