JVM类加载三步解读: 双亲委派模型如何维护Java生态

欢迎浏览高耳机的博客

希望我们彼此都有更好的收获

感谢三连支持!  

        🙉Java是面向对象编程,一切皆对象。这些对象是如何从一堆代码变成程序中的一部分?Java虚拟机(JVM)在这个过程中扮演了至关重要的角色。当你的代码通过编译器转换成.class文件,再到运行时的动态加载,JVM内部的类加载机制确保了这一切的顺利进行。

        本文将带你探索Java类加载,从类的加载、连接到初始化,一步步解读JVM如何管理类的生命周期。

目录

类加载过程

加载

连接

验证

准备

解析

初始化 

双亲委派模型

模型概述

类加载器层次

核心目的

破坏双亲委派模型 


类加载过程

        🥝《Java虚拟机规范》是由Oracle发布的Java领域最重要和最权威的著作,完整且详细地描述了JVM的各个组成部分。

PS:本文以下部分,默认都是使用HotSpot,即Oracle Java默认的虚拟机为前提来进行介绍的。

        🍇在Java虚拟机(JVM)中,类的加载过程是实现Java程序动态性的关键。整个类加载过程大致可以分为三个主要阶段:加载、连接和初始化。

加载

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

1)通过一个类的全限定名来获取定义此类的二进制字节流。(例如,如果有一个类MyClass位于包com.example.myapp中,那么这个类的全限定名就是com.example.myapp.MyClass。)

2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3)在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口。 

连接

        🍊JVM类加载过程通常被描述为包含五个步骤,但实际上,这包含了“连接”阶段被细分的三个更具体的操作。因此,可以说JVM类加载实际上涉及三个详细步骤。

1) 验证

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

验证选项: • 文件格式验证 • 字节码验证 • 符号引用验证... 

        这就使我们需要确保编译时使用的JDK版本要和运行时使用的JDK版本一致,或者向前兼容。

2) 准备

        🥥JVM在准备阶段为类变量(即静态变量)分配内存,并设置类变量初始值。

public static int value = 123;

        在准备阶段,value的值会被初始化为0,而不是123。 这样做避免了内存中残留的数据被当前程序错误的使用,从而产生bug。

3) 解析

        🍑将常量池内的符号引用替换为直接引用的过程,也就是将常量池中的引用转换为直接指向内存的引用。

Class Test {String s = "Hello";
}

        在这个时刻,字符串常量s已经存在于.class文件中。然而,这里并没有提到“地址”这个概念,因为在.class文件的上下文中,我们不直接使用内存地址。相反,我们使用“偏移量”来指代字符串常量s在内存中的位置。

初始化 

        🍅初始化阶段,Java虚拟机真正开始执行类中编写的Java程序代码,将主导权移交给应用程序。初始化阶段就是执行类构造器方法的过程。

Class Test {static int a = 123;
}

        现在,是真正执行将 123 赋值给 a 的过程。执行了类中的静态代码块,并且这个操作也会触发对父类(即超类)的加载过程。

        🫐回看这个过程,是否对类加载机制有了一个基本的了解?

双亲委派模型

        双亲委派模型是JVM中类加载机制的核心概念之一。双亲实际上指代的是子类与父类,而不是广义上的概念。

模型概述

        🍎当一个类加载器接收到加载类的请求时,它不会立即尝试加载这个类。相反,它会将请求传递给其父类加载器来处理。这个过程会一直向上传递,直到最顶层的父类启动类加载器。只有在父类加载器表示无法找到所需类的文件时,也就是说它自己的搜索范围内没有这个类,子加载器才会接手并尝试加载这个类。

        这种机制被称为类加载的委派模型。简而言之,类加载器会逐级向上请求帮助,直到最顶层,如果上级无法处理,才会由下级自己来加载类。

类加载器层次

        启动类加载器(Bootstrap ClassLoader):使用C++实现,是虚拟机自身的一部分,负责加载JAVA_HOME/jre/lib目录中的核心类库。

        扩展类加载器(Extension ClassLoader):由Java语言实现,继承自ClassLoader类,负责加载JAVA_HOME/jre/lib/ext目录或者由系统属性java.ext.dirs指定位置中的类库。

        应用程序类加载器(Application ClassLoader):也称为系统类加载器,由Java语言实现,继承自ClassLoader类,负责加载环境变量classpath或系统属性java.class.path指定路径下的类库。

        自定义类加载器  :根据需求定制的类加载器。

        🥑当应用程序类加载器开始工作时,它会逐层向上请求其父加载器协助加载类。在这个过程中,如果任何一个加载器成功地加载了所需的类,那么这个类就会被进一步处理。如果所有上级加载器都未能找到并加载这个类,最终请求会返回到应用程序类加载器。

        如果这时应用程序类加载器也无法找到对应的.class文件,就会报告一个错误,抛出ClassNotFoundException异常。

        简而言之,类加载是一个从应用程序类加载器开始的逐级向上请求的过程,如果最终无法加载类,就会报告找不到类的异常。

核心目的

        防止类重复加载:当A类和B类共享一个共同的父类C时,如果在A类加载过程中C类已经被加载,那么在B类加载时就无需再次加载C类。这样可以避免同一个类被重复加载。

        保障核心API的安全性:通过使用双亲委派模型,可以确保Java的核心API不被随意篡改。如果没有这种模型,每个类加载器都可能加载自己的版本,这可能导致系统中存在多个不同的Object类实例,其中一些可能是用户自定义的,这样就会威胁到系统的安全性。

        

        双亲委派模型定义了Java标准库的最高优先级,扩展库其次,第三方库最低,确保了Java核心库的单一性和安全性。

破坏双亲委派模型 

        🥝尽管双亲委派模型有许多优点,但在某些场景下,比如JDBC的实现,它并不完全适用。

JDBC的Driver接口定义在JDK中,而具体的实现则由各个数据库服务商提供。

        例如MySQL的驱动包。当我们查看DriverManager的源码时,会发现它实际上是位于系统的核心库rt.jar中,由顶层的启动类加载器(Bootstrap ClassLoader)加载。然而,在DriverManagergetConnection方法中,它实际上是使用子类加载器,也就是线程上下文类加载器(Thread.currentThread().getContextClassLoader())来加载具体的数据库驱动实现,例如MySQL的Jar包。

        🍇这种做法实际上打破了双亲委派模型的常规流程,因为按照双亲委派模型的原则,所有类的加载都应该由父类加载器来完成。但在JDBC的情况下,由于Driver接口的实现类是由服务商提供的,需要通过子类加载器来加载,这就导致了双亲委派模型的规则被打破了。

        🍉这种设计是为了确保Java核心API的安全性和灵活性,允许在运行时动态加载数据库驱动,而不是在JVM启动时静态确定。


        🙉我们从类的加载、连接到初始化,逐步了解了JVM如何精心管理类的生命周期。双亲委派模型不仅确保了类的一致性和安全性,还为我们提供了一个有序、可预测的类加载环境。通过对双亲委派模型的深入理解,我们能够更好地把握Java程序的行为,优化性能,并确保程序的稳定性。


希望这篇博客能为你理解JVM类加载机制提供一些帮助

如有不足之处请多多指出

我是高耳机

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

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

相关文章

青海摇摇了3天,技术退步明显.......

最近快手上的青海摇招聘活动非常火热,我已经在思考是否备战张诗尧的秋招活动。开个玩笑正片开始: 先说一下自己的情况,大专生,20年通过校招进入杭州某软件公司,干了接近4年的功能测试,今年年初&#xff0c…

SpringBean生命周期之PostConstruct、PreDestroy详解

在Spring框架中,Bean的生命周期是一个复杂的过程,涉及多个阶段,其中PostConstruct和PreDestroy注解在Bean的初始化和销毁阶段发挥着重要作用。以下是对这两个注解的深入理解: 一、PostConstruct注解 定义与来源 PostConstruct源自…

基于阿里云Ubuntu22.04 64位服务器Java及MySql环境配置命令记录

基于阿里云Ubuntu22.04 64位服务器Java及MySql环境配置命令记录 Java 23 离线环境配置MySql 环境配置MySQL常用命令 Java 23 离线环境配置 下载 Ubuntu环境下 Java 23 离线包 链接: java Downloads. 在Linux环境下创建一个安装目录 mkdir -p /usr/local/java将下载好的jdk压缩…

逆向分析:利用标志位进行爆破破解

信息收集 查程序编写信息 所用工具Detect It Easy Delphi编写,根据此信息选择DeDeDark进行反编译进一步收集可用信息 反编译程序进行信息收集 所用工具DeDeDark 载入要分析的主程序点击[开始处理]进行分析 注:主程序即软件主题程序(长见软件安装完毕…

【工具变量】上市公司企业研发不确定性数据(2013-2023年)

一、测算方式:参考顶刊《中国工业经济》孙薇(2023)老师的做法,本文从专利的申请与授权的视角出发,以企业当年申请的发明专利中最终未被授权的比例度量研发不确定性 (uc)。这是因为,相…

centos部署SkyWalking并在springcloud项目中用法举例

文章目录 场景SkyWalking介绍部署部署Storage [单机版Elasticsearch]部署SkyWalking OAP [下载地址](https://skywalking.apache.org/downloads/#SkyWalkingAPM)部署SkyWalking Java AgentspringCloud 使用举例 场景 SkyWalking是应用性能监控平台,可用于分布式系统…

[ACL 2024] ReFT: Reasoning with REinforced Fine-Tuning

Contents IntroductionMethodExperimentsReferences Introduction 作者提出 Reinforced Fine-Tuning (ReFT) 进行在线强化学习,帮助模型输出正确的推理步骤,总体感觉在线学习的思路和 STaR 非常相似,就是把 SFT 换成了 PPO… Method Warm-…

深度优先的艺术:探索二叉树的深搜算法精髓

文章目录 前言☀️一、计算布尔二叉树的值🌙解法⭐代码 ☀️二、求根节点到叶节点数字之和🌙解法⭐代码 ☀️三、二叉树剪枝🌙解法⭐代码 ☀️四、验证二叉搜索树🌙解法☁️步骤⭐代码 ☀️五、二叉搜索树中第k小的元素&#x1f3…

python学opencv|读取图像(五)读取灰度图像像素

【1】引言 前序学习了图像的基本读取,掌握了imread()、imshow()和imwrite()函数的基本功能和使用技巧,参考文章链接为: python学opencv|读取图像-CSDN博客 然后陆续掌握了彩色图像保存、图像放大和缩小以及对imshow()函数的大胆尝试技巧&a…

基于yolov8的SAR影像目标检测系统,支持图像、视频和摄像实时检测【pytorch框架、python源码】

更多目标检测、图像分类识别、目标追踪等项目可看我主页其他文章 功能演示: 基于yolov8的SAR影像目标检测系统,支持图像、视频和摄像实时检测【pytorch框架、python源码】_哔哩哔哩_bilibili (一)简介 基于yolov8的SAR影像目标…

ESP32开发 云调试

https://blog.csdn.net/weixin_43794311/article/details/128722001 VScode支持的仿真平台 https://docs.wokwi.com/zh-CN/vscode/getting-started 编译:Ctrl Alt B上传并重启模拟器:CtrlShifB Wokwi:Start Simulator调试:CtrlShifB Wokwi…

模版方法模式的理解和实践

在软件开发中,设计模式为我们提供了一套经过验证的解决方案,用于解决常见的设计问题。其中,模版方法模式(Template Method Pattern)是一种行为设计模式,它定义了一个算法的框架,并允许子类在不改…

MySQL--》如何在SQL中巧妙运用函数与约束,优化数据处理与验证?

目录 函数使用 字符串函数 数值函数 日期函数 流程函数 约束 函数使用 函数是指一段可以直接被另一段程序调用的程序或代码,在mysql当中有许多常见的内置函数,接下来开始对这些内置函数及其作用进行简单的讲解和使用: 字符串函数 my…

归有光,情感与真实的独行者

归有光,字熙甫,号震川,生于明孝宗弘治十年(公元1507年),卒于明穆宗隆庆五年(公元1571年),享年64岁。他是中国明代著名的散文家、文学家和史学家,其散文风格清…

计算机网络-Wireshark探索ARP

使用工具 Wiresharkarp: To inspect and clear the cache used by the ARP protocol on your computer.curl(MacOS)ifconfig(MacOS or Linux): to inspect the state of your computer’s network interface.route/netstat: To inspect the routes used by your computer.Brows…

Vue3小兔鲜电商项目

创建项目 npm install 装包

美畅物联丨视频接入网关如何配置 HTTPS 证书

在安防领域,视频接入网关(Video Access Gateway,VAG)是视频监控系统的重要组成部分,其职责是把视频数据从前端设备传输至后端服务器。配置HTTPS证书后,可对视频流进行加密传输,避免数据在网络传…

fastcam编程套料软件

Fastcam是一款功能强大的专业软件,以下是对它的具体介绍: 基本信息 • Fastcam自1982年推出首个交互式CNC编程和套料系统后,一直不断更新发展. • 它是为数控火焰、等离子、激光和水射流切割机等数控切割机开发的编程套料软件. 主要功能模…

【大语言模型】LangChain ModelsIO与Models I/O Promopts详解

【大语言模型】LangChain ModelsIO与Prompts详解 一、LangChain ModelsIO1、简介2、Models I/O 的应用场景3、Models I/O 主要模块3.1、Prompts3.2、Modelsa、MESSAGES 类型 3.3、Output Parsers 二、LangChain ModelsIO Prompts1、简介2、Prompts 的优点3、实战示例3.1、Promp…

MicroBlaze软核开发(三):DDR + FLASH

实现功能:使用 MicroBlaze软核,配置 DDR、Flash 接口,并将程序烧写固化到Flash,每次启动 FPGA 时自动运行 Flash 中的程序 。 Vivado版本:2018.3 FPGA:Xilinx Artix-7 系 目录 引言 Vivado部分&#xff1…