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 载入要分析的主程序点击[开始处理]进行分析 注:主程序即软件主题程序(长见软件安装完毕…

再次回首人生的四个部分

概述 今日部门聚餐,讲了明年的业绩组成及如何实现,更多的从侧面反应了群体人之间的差异点。 人生四部分 这里说的可能不是太全面,但是是突感而发,再此总结而已。 出身 能力 选择 机遇 我们无法左右自己的出身,…

C语言蓝桥杯2023年省赛真题

文章目录 持续更新中...第一题题目描述输入格式输出格式样例输出提示 2 第二题题目描述 第三题题目描述输入格式输出格式样例输入样例输出 第四题题目描述输入格式输出格式样例输入样例输出提示 第四题题目描述输入格式输出格式样例输入样例输出提示 第五题题目描述输入格式输出…

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

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

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

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

MISRA C2012学习笔记(10)-Rules 8.15

文章目录 8.15 控制流(Control flow)Rule 15.1 不应使用 goto 语句Rule 15.2 goto 语句仅允许跳到在同一函数中声明的稍后位置的标签Rule 15.3 goto 语句引用的标签必须在 goto 语句所在代码块或包含该代码块的上级代码块中声明Rule 15.4 最多只能有一个用于终止循环语句的 bre…

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

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

DDOS分布式拒绝服务攻击

DDOS分布式拒绝服务攻击 简单来说 传统的DOS就是一台或者多台服务对一个受害目标(服务器,路由,ip,国家)进行攻击,当范围过大时就是DDOS。目的就是通过大规模的网络流量使得正常流量不能访问受害目标&…

JavaSE——泛型编程

一、为什么要引入泛型编程 看这段代码: //传统方法: ArrayList list new ArrayList(); list.add(new Dog("小黄",5)); list.add(new Dog("小黑",1)); list.add(new Dog("小财",10)); //编译器发现不了这种问题&#xff…

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

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

VB.net进行CAD二次开发(二)与cad交互

开发过程遇到了一个问题&#xff1a;自制窗口与控件与CAD的交互。 启动类&#xff0c;调用非模式窗口 Imports Autodesk.AutoCAD.Runtime Public Class Class1 //CAD启动界面 <CommandMethod("US")> Public Sub UiStart() Dim myfrom As Form1 New…

linux ls -l 输出 drwxr-xr-x 2 root root 4096 Dec 5 21:48 rootTest 是什么意思

在Linux系统中&#xff0c;ls -l命令用于以长格式列出目录内容的详细信息。输出的一行通常包含以下部分&#xff1a; drwxr-xr-x 2 root root 4096 Dec 5 21:48 rootTest这一行的各个部分意义如下&#xff1a; drwxr-xr-x&#xff1a;这是文件类型和权限的标识。 第一个字符d…

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

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

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

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

2.Flink的项目初始化和Hello-world

目录 1.Flink项目初始化 2.Hello-world 1.Flink项目初始化 新建maven项目或者gradle项目&#xff0c;这里使用maven项目为例。 在项目的pom.xml文件中添加Flink依赖&#xff0c;如下所示&#xff0c;为Hello-World例子的最小依赖&#xff1a; <properties><maven.c…

ESP32开发 云调试

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

如何写出一篇好的论文?

写出一篇好的论文需要综合多方面的要素&#xff0c;从选题到最终成文&#xff0c;每一步都至关重要。首先&#xff0c;明确研究主题和目标&#xff0c;确保选题具有创新性、可行性和实际意义。接着&#xff0c;进行深入的文献检索和综述&#xff0c;了解当前领域的研究现状和前…