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

JVM 学习—— 类加载机制

前言

        在上一篇文章中,荔枝梳理了有关Java中JVM体系架构的相关知识,其中涉及到的有关Java类加载机制的相关知识并没有过多描述。那么在这篇文章中,荔枝会详细梳理一下有关JVM的类加载机制和双亲委派模型的知识,希望能够帮助到有需要的小伙伴~~~


文章目录

前言

一、JVM中类加载过程

加载

连接

初始化

二、类加载器

类加载器的分类 

类加载器的特点

三、双亲委派机制

双亲委派机制流程

双亲委派机制的优点

如何打破双亲委派机制 

总结


一、JVM中类加载过程

        在前面JVM体系结构一文中我们知道运行Java程序的过程首先编译器会将.Java文件编译成字节码文件并由JVM中的类加载机制进行加载和并发送指令给执行引擎执行。而对于类来说,它的生命周期主要经历7个阶段:加载、验证、准备、解析、初始化、使用、卸载,其中前五个阶段就是类加载的过程。需要注意的是,类加载过程并不是严格意义上的按顺序经历上面的五个阶段,这些阶段可能会互相混合、交叉运行。接下来看看五个阶段的类加载的内容:

加载

        加载阶段是将类的字节码文件加载到JVM中的内存中,并在内存中生成对应的Class对象。类加载器根据类的全限定名(类的包名+类名)来查找字节码文件,找到后读取字节码数据,转化成方法区的运行时数据结构并在Java堆中生成对应的Java.lang.Class对象,作为对方法区中这些数据的访问入口。

类加载器可以是Java虚拟机自带的类加载器,也可以是自定义的类加载器。

连接

我们一般把验证、准备和解析这三个状态归到一块作为连接的阶段, 连接阶段将类的字节码文件中的符号引用转换为直接引用,生成可执行的代码。

验证

验证阶段的目的是保证字节码文件中的字节流内容符合Java虚拟机的规范。一般来说验证阶段会进行文件格式验证、元数据验证、字节码验证和符号引用验证。

  • 文件格式验证:验证字节流是否符合Class文件格式的规范。例如:是否以0xCAFEBABE开头、主次版本号是否在当前虚拟机的处理范围之内、常量池中的常量是否有不被支持的类型;
  • 元数据验证:对字节码描述的元数据信息进行语义分析,要符合Java语言规范。例如:是否继承了不允许被继承的类(例如final修饰过的)、类中的字段、方法是否和父类产生矛盾等;
  • 字节码验证:对类的方法体进行校验分析,确保这些方法在运行时是合法的、符合逻辑的。
  • 符号引用验证发生在解析阶段,符号引用转为直接引用的时候,例如:确保符号引用的全限定名能找到对应的类、符号引用中的类、字段、方法允许被当前类所访问等等

准备

在准备阶段类的静态字段信息会得到内存分配,并设置为初始值,其中静态字段信息指的是被static关键字修饰的变量。

解析

这个阶段,虚拟机会把这个Class文件中,常量池内的符号引用转换为直接引用。主要解析的是类或接口、字段、类方法、接口方法、方法类型、方法句柄等符号引用。

初始化

        初始化阶段是类加载的最后一个阶段,也是真正执行类的初始化代码块和静态变量初始化的阶段。在这个阶段,JVM会按照程序员指定的顺序执行类的静态初始化代码块和静态变量的初始化,这些初始化代码会在类第一次使用时被调用。初始化是类加载过程中的最后一个步骤,直到此阶段完成,类才算完全加载并可以使用。 

需要注意的是:在整个类加载过程中,类加载器负责加载和连接阶段,而初始化阶段由JVM负责。 


二、类加载器

类加载器,其实就是一个可以将Java编译后的字节码文件加载为可以被java.lang.class实例化的工具,负责将字节码文件转化成为JVM内部的Class对象。

类加载器的分类 

启动类加载器(Bootstrap ClassLoader):负责加载%JAVA_HOME%/lib 目录,或者被 -Xbootclasspath 参数制定的路径,例如 jre/lib/rt.jar 里所有的class文件。由C++实现,不是ClassLoader子类。

拓展类加载器(Extension ClassLoader):负责加载Java平台中扩展功能的一些jar包,包括<JAVA_HOME>\lib\ext 目录中 或 java.ext.dirs 指定目录下的jar包。由Java代码实现。

应用程序类加载器(Application ClassLoader):我们自己开发的应用程序,就是由它进行加载的,负责加载ClassPath路径下所有jar包。

自定义类加载器(User ClassLoader):通过继承java.lang.ClassLoader实现自定义的类加载 

类加载器的特点

  • 按需加载:无需在程序一开始运行的时候加载所有的字节码文件,而是在程序运行的过程中,动态按需加载,字节码的来源也很多,压缩包jar、war中,网络中,本地文件等。类加载器按需加载的特点为热部署,热加载做了有力支持。
  • 全盘负责:当一个类加载器加载一个类时,这个类所依赖的、引用的其他所有类都由这个类加载器加载,除非在程序中显式地指定另外一个类加载器加载。所以破坏双亲委派不能破坏扩展类加载器以上的顺序。
  • 双亲委派:类加载器遵循双亲委派模型,即加载类时,首先委派给父类加载器处理。只有父类加载器无法加载时,才由子类加载器尝试加载。双亲委派模型保证了类的加载在整个类加载器层次中的一致性,避免类的重复加载和冲突。
  • 自定义扩展:开发者可以继承java.lang.ClassLoader类,实现自定义的类加载器。通过自定义类加载器,可以实现特定的类加载行为,打破双亲委派模型,加载特定位置的类文件,满足特定需求。

三、双亲委派机制

        JVM 并不是在启动时就把所有的Class文件都加载一遍,而是程序在运行过程中用到了这个类才去加载,而通常这个类加载过程就会基于双亲委派机制来实现。双亲委派是JVM中对类加载的一种模式机制,即任意一个类在接到一个类的加载请求时,都会先加载其父类,若父类无法加载(或无父类)的情况下,再尝试自己加载或者给子类加载,总的来说就是向上委派、向下加载的过程。

双亲委派机制流程

用直白的语言来描述一下双亲委派的流程:

  • 在当前的类加载器收到类加载请求时,会首先检查是否之前加载过该类,如果加载过就将该类所对应的Class对象返回出去并完成类加载请求响应。
  • 如果该类没有被加载过,当前的类加载器则会将该加载请求委派给父类加载器处理。父类加载器按照同样的递归方式向上委派该类加载请求,即首先检查该类是否已经被加载过,如果已经被加载过,则返回对应的Class对象。如果父类加载器也没有加载过这个类,则将加载请求再委派给父类的父类的加载器,直到达到顶层的启动类加载器。
  • 如果顶层的启动类加载器也没有加载过这个类,则当前类加载器尝试自己加载这个类。如果启动类加载器加载该类失败(加载路径下找不到该class文件),就会将加载向下委派给其子类的类加载器直至自定义类加载器;
  • 如果自定义类加载器也无法加载该类,就会排除ClassNotFound异常。

双亲委派机制的优点

前面我们已经知晓双亲委派机制是向上委派、向下加载的。这种执行方式就能够有效保证了类都是在同一个类加载器中加载并构造对象的。同时由于类总是从父类中开始加载的,也保证了官方JDK代码包的安全性,具体的优点如下:

  1. 避免类的重复加载:通过双亲委派机制,当一个类加载器加载一个类时,它会首先委派给父类加载器处理。如果父类加载器已经加载了这个类,就不需要再次加载,直接返回已加载的Class对象。这样可以避免同一个类被不同的类加载器加载,保证类的唯一性,避免类的重复加载,节省了内存空间。

  2. 保证代码安全性:通过双亲委派机制,JVM的核心类库(如java.lang、java.util等)由启动类加载器加载,这些类库被放置在JVM的核心路径下,由Java官方提供,保证了这些类的安全性和稳定性。用户自定义的类则由应用类加载器加载,用户可以控制这些类的访问权限,从而提高了应用程序的安全性。

  3. 确保类的一致性:通过双亲委派机制,JVM保证了类加载的一致性。无论是系统核心类库还是用户自定义的类,它们都是由类加载器层次结构中的某个类加载器加载的,这样可以保证类在整个JVM中的唯一性和一致性,避免类的冲突和不一致性。

  4. 代码隔离:双亲委派机制将类的加载委派给父类加载器处理,子类加载器无法直接访问父类加载器加载的类,这样实现了类加载器之间的代码隔离。不同的类加载器可以加载相同名称的类,但它们加载的类是不同的,从而实现了类的隔离,不同的类加载器可以加载自己的版本,相互之间不会相互干扰。

如何打破双亲委派机制 

        在某些特定的场景下,我们需要打破JVM类加载中的双亲委派机制,比如我们想要加载一些于JVM核心类库同名的类并且希望这些类由用户自定义的类加载器加载,而不是受到父类加载器的影响。打破双亲委派机制的两种方式:

  • 自定义类加载器并继承ClassLoader类,重写该类的方法如findClass和loadClass;
  • 通过线程上下文类加载器的传递性并让父类加载器调用子类加载器的加载动作。

总结

        以上就是JVM中有关类加载机制的相关知识点了,其中最重要的就是双亲委派机制的理解和两种打破方式的了解,这里其实荔枝写的不是特别详细,可能需要在阅读完源码之后才能输出更有质量的自我理解吧。大致了解了JVM的类加载机制,接下来的文章中荔枝可能会输出有关JVM另一个核心知识点:GC垃圾回收机制的相关知识的梳理,希望能够帮助到大家哈哈哈~~~

今朝已然成为过去,明日依然向往未来!我是小荔枝,在技术成长的路上与你相伴,码文不易,麻烦举起小爪爪点个赞吧哈哈哈~~~ 比心心♥~~~

相关文章:

JVM 学习—— 类加载机制

前言 在上一篇文章中&#xff0c;荔枝梳理了有关Java中JVM体系架构的相关知识&#xff0c;其中涉及到的有关Java类加载机制的相关知识并没有过多描述。那么在这篇文章中&#xff0c;荔枝会详细梳理一下有关JVM的类加载机制和双亲委派模型的知识&#xff0c;希望能够帮助到有需要…...

C#实现int类型和字节流的相互在转化

通过TCP协议进行数据传输时&#xff0c;需要将所有传输的内容转为字节流&#xff0c;这里就用到了将int型的数据转为字节流的。代码如下&#xff1a; public static byte[] BytesConvertToInt(int vel) {byte[] hex new byte[4];hex[3] (byte)(vel >> 24) & 0xff)…...

Centos设置固定IP地址,外网访问

查看网络信息 一般会看到enp0s3的网络配置 ip address切换至网络配置路径 cd /etc/sysconfig/network-scripts/编辑配置 vi ifcfg-enp0s3 编辑配置 主要修改 静态ip:BOOTPROTOdhcp --> OOTPROTOstaticDNS(訪問外網):DNS1114.114.114.114本机ip: 192.168.70.121子网掩码…...

非线性弹簧摆的仿真(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

css实现文字颜色渐变+阴影

效果 代码 <div class"top"><div class"top-text" text"总经理驾驶舱">总经理驾驶舱</div> </div><style lang"scss" scoped>.top{width: 100%;text-align: center;height: 80px;line-height: 80px;fo…...

C++学习笔记总结练习:关联容器

关联容器 0 关联容器概述 关联容器与顺序容器的区别 关联容器和顺序容器有着根本不同。关联容器中的元素是按关键字来把偶才能和访问的。书序容器中的元素是按他们在容器中的位置来顺序保存和访问的。 两个基础类型 map:键值对key-value。关键字是索引&#xff0c;值表示与…...

TypeScript技能总结(二)

typescript是js的超集&#xff0c;目前很多前端框架都开始使用它来作为项目的维护管理的工具&#xff0c;还在不断地更新&#xff0c;添加新功能中&#xff0c;我们学习它&#xff0c;才能更好的在的项目中运用它&#xff0c;发挥它的最大功效 //readonly 只能修饰属性&#x…...

整理一些Postgresql工作中常用面试中会问的问题---Postgresql面试题001

1.什么是Postgresql TOAST? TOAST (The Oversized-Attribute Storage Technique,超大尺寸字段存储技术)主要用于存储大字段的值。 PostgreSQL 页面(page)大小是固定的(通常为8KB),且不允许tuples跨多个页面存储。因此不能存储非常大的字段值。为了克服这个限制,大字段…...

Xposed回发android.os.NetworkOnMainThreadException修复

最近用xposed进行hook回发的时候&#xff0c;又出现了新的问题&#xff1b; android.os.NetworkOnMainThreadException&#xff1b; 在Android4.0以后&#xff0c;写在主线程&#xff08;就是Activity&#xff09;中的HTTP请求&#xff0c;运行时都会报错&#xff0c;这是因为…...

【Leetcode】二叉树的最近公共祖先,二叉搜索树转换成排好序的双向链表,前序遍历与中序遍历构造二叉树

一.二叉树的最近公共祖先 链接 二叉树的最近公共祖先 题目再现 『Ⅰ』思路一&#xff1a;转换成相交链表问题 观察上图&#xff0c;节点1和节点4的最近公共祖先是3&#xff0c;这是不是很像相交链表的问题&#xff0c;关于相交链表&#xff0c;曾经我在另一篇文章里写到过&a…...

途乐证券|互联金融概念爆发,安硕信息“20cm”涨停,高伟达等大涨

互联金融概念4日盘中强势拉升&#xff0c;截至发稿&#xff0c;安硕信息“20cm”涨停&#xff0c;高伟达、卓创资讯、慧博云通涨超12%&#xff0c;恒银科技、极点软件亦涨停&#xff0c;指南针涨超9%&#xff0c;金证股份涨逾7%。 高伟达昨日在投资者互动平台表明&#xff0c;公…...

计数排序算法

计数排序 计数排序说明&#xff1a; 计数排序&#xff08;Counting Sort&#xff09;是一种非比较性的排序算法&#xff0c;它通过统计元素出现的次数&#xff0c;然后根据元素出现的次数将元素排列在正确的位置上&#xff0c;从而实现排序。计数排序适用于非负整数或者具有确…...

企业高性能web服务器-nginx

1.nginx简介&#xff1a; nginx是企业高可用的web服务器&#xff0c;nginx也可用来做反向代理服务器器&#xff0c;具有高并发&#xff0c;占用资源少&#xff0c;功能丰富&#xff0c;也可以作为简单的负载均衡。 nginx在企业中的功能&#xff1a; web服务软件 反向代理服务器…...

GaussDB数据库的元数据及其管理简介

目录 一、前言 二、元数据简介 1、元数据定义 2、元数据分类 3、数据库元数据管理 三、GaussDB数据库的元数据管理 1、GaussDB数据库的元数据管理 2、通过“SQL 系统表/系统视图/系统函数”的方式管理&#xff08;采集&#xff09;元数据 1&#xff09;获取表、视图及…...

合并两个有序链表 LeetCode热题100

题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 思路 遍历两个链表比较大小&#xff0c;按从小到大添加到链表即可。 代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* List…...

【C++】模拟实现string

目录 &#x1f31e;专栏导读 &#x1f31b;定义string类 &#x1f31b;构造函数 &#x1f31b;拷贝构造函数 &#x1f31b;赋值函数 &#x1f31b;析构函数 &#x1f31b;[]操作符重载 &#x1f31b;c_str、size、capacity函数 &#x1f31b;比较运算符重载 &#…...

AI智慧安监视频监控汇聚平台EasyCVR调用接口出现跨域现象该如何解决?

视频监控汇聚EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视…...

无人机机巢有哪些,无人机机场/机场的主要分类

随着无人机技术的飞速发展&#xff0c;无人机已经渗透到了物流、农业、救援、公共安全等多个领域。而为了使这些无人机能更加高效、灵活地运行&#xff0c;一个新的概念应运而生&#xff0c;那就是无人机机巢&#xff08;UAV Nest&#xff09;。复亚智能无人机机巢是一种供无人…...

联想存储 HH0305_DE4000H 划分卷组、卷、主机

创建卷组 可使用卷组来创建可供主机访问的一个或多个卷。卷组是具有共同特性&#xff08;如 RAID 级别和容量&#xff09;的卷的容器。 关于本任务 如果拥有容量较大的驱动器且可以在控制器之间分发卷&#xff0c;则为每个卷组创建多个卷可以很好地利用存储容量和保护数据。…...

【Python机器学习】实验08 决策树

文章目录 决策树1 创建数据2 定义香农信息熵3 条件熵4 信息增益5 计算所有特征的信息增益&#xff0c;选择最优最大信息增益的特征返回6 利用ID3算法生成决策树7 利用数据构造一颗决策树Scikit-learn实例决策树分类决策树回归Scikit-learn 的决策树参数决策树调参 实验1 通过sk…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]

报错信息&#xff1a;libc.so.6: cannot open shared object file: No such file or directory&#xff1a; #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...

SQL注入篇-sqlmap的配置和使用

在之前的皮卡丘靶场第五期SQL注入的内容中我们谈到了sqlmap&#xff0c;但是由于很多朋友看不了解命令行格式&#xff0c;所以是纯手动获取数据库信息的 接下来我们就用sqlmap来进行皮卡丘靶场的sql注入学习&#xff0c;链接&#xff1a;https://wwhc.lanzoue.com/ifJY32ybh6vc…...