【JVM】类加载机制及双亲委派模型

news2024/12/25 9:28:35

目录

一、类加载过程

1. 加载

2. 连接

a. 验证

b. 准备

c. 解析

3. 初始化

二、双亲委派模型 

类加载器 

双亲委派模型的工作过程

双亲委派模型的优点


一、类加载过程

JVM的类加载机制是JVM在运行时,将 .class 文件加载到内存中并转换为Java类的过程。它是Java语言实现跨平台特性的核心之一。

对于一个类来说,它的生命周期是这样的:

其中,类加载的过程主要可以分成 5 个步骤(前 5 步),中间 3 步都属于连接,所以也可以说类加载过程主要分成 3 个步骤:

1. 加载

2. 连接

  • 验证
  • 准备
  • 解析

3. 初始化

下面我们来看每个步骤的具体执行内容:

1. 加载

“加载”阶段是整个“类加载”过程中的一个阶段,它和类加载是不同的。

加载阶段是指将类的字节码文件加载到内存中的过程。在加载 Loading 阶段,Java虚拟机需要完成以下三件事情:

1)通过一个类的全限定名来获取定义此类的二进制字节流。(全限定名,例如:java.lang.String)

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

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

2. 连接

a. 验证

确保加载的类符合JVM规范和Java语言规范,即确保读到的 .class 文件(字节码文件),是合法的格式。

文件格式如下图所示,此处就不详细介绍了。

b. 准备

给类的静态变量分配内存空间,并设置类变量的默认初始值。

比如此时有这样一行代码:

public static int value = 123;

它是初始化 value 的值为0(默认值),而非 123。

c. 解析

解析阶段是 JVM 将类、接口、字段和方法(运行时常量池)的符号引用解析为直接引用。

  • 符号引用的获取: 在加载阶段和连接阶段之前,Java虚拟机会将类、接口、字段和方法的符号引用存储在运行时常量池中。解析阶段首先要做的就是从运行时常量池中获取符号引用。

  • 符号引用的匹配: 获取到符号引用后,解析阶段会尝试将这些符号引用匹配到目标对象(类、接口、字段或方法)的直接引用。匹配的过程包括查找目标对象在内存中的位置以及确定访问权限等。

  • 直接引用的生成: 一旦符号引用成功匹配到目标对象,解析阶段就会生成对应的直接引用。直接引用是指直接指向内存中目标对象的指针或偏移量,它能够直接在程序中被使用。

  • 解析结果的存储: 解析阶段最终会将生成的直接引用存储在运行时常量池中,以便后续的使用。

3. 初始化

初始化阶段是类加载过程的最后一个阶段,主要负责执行类变量的赋值操作和静态代码块的初始化。

  • 执行类变量的赋值操作,即按照程序员在代码中指定的初始值为静态变量赋值。这些值可以是程序中直接赋予的值,也可以是静态代码块中的计算结果。
  • 如果类中存在静态代码块,则会按照在代码中的顺序执行静态代码块中的内容。静态代码块中可以包含任意合法的 Java 代码,用于执行一些静态初始化操作。

上述的一系列类加载过程,可以简单概况为以下内容:

  1. 加载(Loading): 加载阶段是指将类的字节码文件加载到内存中的过程。当程序中使用到某个类时,JVM会通过类的全限定名(Fully Qualified Name)来加载类。类加载器会根据类的全限定名在文件系统或网络中查找相应的.class文件,并将其加载到内存中。

  2. 连接(Linking): 连接阶段包括验证、准备和解析三个步骤:

    • 验证(Verification): 确保加载的类符合JVM规范和Java语言规范,以防止恶意代码的注入。
    • 准备(Preparation): 为类的静态变量分配内存空间,并设置默认初始值。
    • 解析(Resolution): 将类、接口、字段和方法的符号引用解析为直接引用,以便后续执行。
  3. 初始化(Initialization): 初始化阶段是类加载过程的最后一个阶段,它负责执行类构造器的<clinit>方法,即对类的静态变量进行赋值操作和执行静态代码块。

二、双亲委派模型 

提到类加载机制,就不得不提“双亲委派模型”。它是 Java 类加载机制中的一种设计思想,JVM的类加载机制采用的就是双亲委派模型。

类加载器 

在 JVM 中,有一个重要的组件称为“类加载器”,它负责加载 Java 类文件到 JVM 中(根据类的全限定名来查找并加载对应的类文件,例如:java.lang.String)。JVM 中的类加载器默认有以下三种:

  1. 启动类加载器(Bootstrap Class Loader): 它是 JVM 的内置类加载器,负责加载 Java 核心类库(rt.jar)等核心类文件(标准库),是整个类加载器层次结构的顶层。由于它是用本地代码实现的,所以在 Java 中无法直接获取对其的引用。

  2. 扩展类加载器(Extension Class Loader): 它是用来加载 Java 平台的扩展库(ext 目录下的jar包)的类加载器。它的父类加载器是启动类加载器。通常情况下,我们可以通过 ClassLoader.getSystemClassLoader().getParent() 获取到扩展类加载器的引用。

  3. 应用程序类加载器(Application Class Loader): 也称为系统类加载器,它是用来加载应用程序的类文件的类加载器,它负责加载类路径(classpath)上指定的类库。它的父类加载器是扩展类加载器。通常情况下,我们可以通过 ClassLoader.getSystemClassLoader() 获取到应用程序类加载器的引用。 

除了上述的三种主要的类加载器之外,JVM 还支持用户自定义的类加载器,用户可以根据需要实现自己的类加载器来加载特定的类文件。用户自定义的类加载器通常继承自  java.lang.ClassLoader 类,并重写其 findClass() 方法来实现类加载的逻辑。

双亲委派模型的工作过程

双亲委派模型的工作过程如下: 

  • 当一个类加载器收到类加载请求时,它不会立即尝试自己去加载这个类,而是先将这个请求委派给它的父类加载器去完成。这个过程会一直向上进行,直到达到最顶层的启动类加载器。只有当父类加载器反馈自己无法完成这个加载请求(即在其搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载这个类。

双亲委派模型的优点

上述设定有以下几个优点:

  1. 安全性: 双亲委派模型可以帮助保证 Java 类库的安全性。由于类加载器会先委托给父类加载器加载类,这样可以防止恶意类被加载到 JVM 中。父类加载器通常是由 JVM 提供的,是由Java官方实现,因此可以信任。这有助于防止在 Java 应用程序中意外加载不安全或有潜在安全风险的类。例如,我们在代码中自己定义了一个 java.lang.String 这样的类,根据双亲委派模型的设定,这个类会被启动类加载器找到并加载,此时加载的是Java核心类,而自定义的 java.lang.String 类实际上是不会被加载的,这就保证了Java核心类库中的类无法被替换。

  2. 避免重复加载类: 双亲委派模型可以避免同一个类被多次加载到 JVM 中。当一个类被加载后,它会被缓存起来,以避免重复加载。这有助于节省内存空间,并且可以确保所有代码都是基于相同的类实例运行。

  3. 统一性: 双亲委派模型可以确保 Java 类库的一致性。因为所有的类加载请求都会经过父类加载器,所以无论是在 Java 应用程序中还是在 Java 核心类库中,都可以保证加载的是同一个类。

双亲委派模型在生活中的类比:

  • 假设你在一家公司工作,你的经理接到了一个任务,他会根据任务的性质和自己的能力来判断是否能够完成这个任务。
  • 如果经理认为自己无法完成任务,他会将任务转交给更高级别的领导,如部门主管或总经理。
  • 只有当更高级别的领导无法完成任务时,任务才会逐级向下转交,直到有可能被转交给你。这种机制确保了任务能够被最适合的人完成,提高了工作效率和质量。

双亲委派模型,是Java虚拟机(JVM)遵循的默认类加载机制。但也有一些方式能够打破这个机制,这里简单介绍:

  • 自定义类加载器: 开发自定义类加载器可以完全改变类加载的方式。通过实现自定义的ClassLoader类,可以实现不同于双亲委派模型的加载行为。例如,可以实现一个不遵循双亲委派模型的类加载器,直接从指定的位置加载类,而不是按照双亲委派模型从上至下逐级加载。

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

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

相关文章

Android 桌面小组件 AppWidgetProvider

Android 桌面小组件 AppWidgetProvider 简介 小组件就是可以添加到手机桌面的窗口。点击窗口可以进入应用或者进入应用的某一个页面。 widget 组件 如需创建 widget&#xff0c;您需要以下基本组件&#xff1a; AppWidgetProviderInfo 对象 描述 widget 的元数据&#xff0…

Linux基础配置(镜像挂载,FQDN)

CentOS基础配置&#xff1a; 以下是appsrv的基础配置脚本&#xff0c;CentOS系统只需要把appsrv改成需要的主机名即可&#xff08;因为Linux基础配置都差不多&#xff0c;写脚本是最省时间的做法&#xff0c;IP地址的配置一般用nmtui图形化界面工具&#xff09; #!/bin/bash …

告别杂乱桌面,开启纯净视界!DeskCover Pro,Mac用户的桌面神器!

DeskCover Pro for Mac是一款专为macOS设计的桌面图标隐藏软件&#xff0c;其主要功能和特点包括&#xff1a; 桌面图标隐藏&#xff1a;通过单击鼠标或按全局热键&#xff0c;可以快速隐藏桌面上的所有图标&#xff0c;为您提供一个干净整洁的工作环境。窗口聚焦&#xff1a;…

ChatGPT-Next-Web漏洞利用分析(CVE-2023-49785)

1. 漏洞介绍 ​ 日常网上冲浪&#xff0c;突然粗看以为是有关Chat-GPT的CVE披露出来了&#xff0c;但是仔细一看原来是ChatGPT-Next-Web的漏洞。漏洞描述大致如下&#xff1a;&#xff08;如果有自己搭建了还没更新的速速修复升级防止被人利用&#xff0c;2.11.3已经出来了&am…

MySQL—多表设计与查询

目录 多表设计 ▐ 数据库设计范式 ▐ 多对一 关系表设计 ▐ 多对多 关系表设计 关联查询 ▐ 概述 ▐ 内连接 ○ 思考&#xff1f; ▐ 左外连接 ▐ 右外连接 多表设计 ▐ 数据库设计范式 • 第一范式&#xff1a;确保每列保持原子性 ( 列不可再分解 ) 例如联系方式…

Mac数据恢复软件快速比较:适用于Macbook的10佳恢复软件

数据丢失导致无数个人和组织每天损失大量资金。更糟糕的是&#xff0c;某些文件具有货币价值和情感意义&#xff0c;使它们不可替代&#xff0c;并使数据恢复成为唯一可行的选择。最好的消息是Mac用户可以从各种数据恢复程序中进行选择。为了帮助您尽可能快速、轻松地恢复丢失的…

弹性云服务器是什么,为何如此受欢迎

云计算作为当下炙手可热的技术领域&#xff0c;已然成为现代企业不可或缺的核心能力。云服务器作为云计算的基石之一&#xff0c;在这个数字化时代发挥着至关重要的作用。而弹性云服务器&#xff0c;作为云服务器的一种演进形式&#xff0c;更是备受瞩目。 弹性云服务器&#…

求知导刊-知网收录//旬刊//如何投稿?

求知导刊-知网收录//旬刊//如何投稿&#xff1f; 《求知导刊》栏目设置 理论探索、课堂教学、教改课改、教育管理、教师教育、教学案例、学科进展、学术论坛。 《求知导刊》征稿对象&#xff1a; 全国科技工作者、教育工作者&#xff0c;各级科技与教育部门的领导者以及管理…

鸿蒙内核源码分析(时间管理篇) | 谁是内核基本时间单位

时间概念太重要了&#xff0c;在鸿蒙内核又是如何管理和使用时间的呢? 时间管理以系统时钟 g_sysClock 为基础&#xff0c;给应用程序提供所有和时间有关的服务。 用户以秒、毫秒为单位计时.操作系统以Tick为单位计时&#xff0c;这个认识很重要. 每秒的tick大小很大程度上决…

AI绘画成果展(第一期)

免费获取更多原图&#xff0c;备注“AI绘画”&#xff0c;可在文章末尾点击名片进qun获取。 免费获取更多原图&#xff0c;备注“AI绘画”&#xff0c;可在文章末尾点击名片进qun获取。

Python密码测试程序

下面是一个简单的 Python 密码测试程序&#xff0c;用于检查用户输入的密码是否符合一些基本的安全要求&#xff0c;如长度、包含字母和数字等。这个程序可以作为一个基本的密码验证器&#xff0c;你可以根据需要进行修改和扩展。 1、问题背景 我们正在编写一个程序&#xff0…

花园牛奶:从靠谱奶牛到新鲜牛奶的匠心之旅

在花园乳业有限公司&#xff0c;我们深知生产出优质牛奶的秘诀——从靠谱的奶牛开始。为此&#xff0c;我们特意引进了品质卓越的荷斯坦奶牛&#xff0c;它们以“黑白花”的优雅身姿&#xff0c;成为了我们牧场上的明星。荷斯坦奶牛以其出色的生产性能和高产奶量而著称&#xf…

uniapp 自定义App UrlSchemes

需求&#xff1a;外部浏览器H5页面&#xff0c;跳转到uniapp开发的原生app内部。 1、uniapp内部的配置&#xff1a; &#xff08;1&#xff09;打开manifest->App常用其他设置&#xff0c;如下&#xff0c;按照提示输入您要设置的urlSchemes&#xff1a; &#xff08;2&am…

3W 1.5KVDC 3KVDC 隔离宽范围输入,单、双输出 DC/DC 电源模块——TP2L-3W 系列

TP2L-3W系列是一款高性能、超小型的电源模块&#xff0c;宽范围2:1,4:1输入&#xff0c;输出有稳压和连续短路保护功能&#xff0c;隔离电压为1.5KVDC、3KVDC工作温度范围为–40℃到85℃。特别适合对输出电压的精度有严格要求的地方&#xff0c;外部遥控功能对您的设计又多一项…

读源码系列文章--开源项目openjob之alarm告警模块

一、背景 告警模块&#xff0c;作为大多数应用都存在的一个基础功能&#xff0c;今天我们就以开源项目openjob 为例&#xff0c;分析其设计及实现。 首先&#xff0c;我们梳理一下需求&#xff1a; 支持多种告警方式&#xff0c;包括钉钉、飞书、微信和webhook。方便业务模块…

多模态大模型学杂了能力反下降?新研究:MoE+通用专家解决冲突

微调&#xff0c;能让通用大模型更加适配具体的行业应用。 但现在&#xff0c;研究人员们却发现&#xff1a; 对多模态大模型做“多任务指令微调”&#xff0c;大模型可能会“学得多错得多”&#xff0c;因为不同任务之间的冲突&#xff0c;导致泛化能力下降。 △多模态指令微…

扩展学习|一文读懂知识图谱

一、知识图谱的技术实现流程及相关应用 文献来源&#xff1a;曹倩,赵一鸣.知识图谱的技术实现流程及相关应用[J].情报理论与实践,2015, 38(12):127-132. &#xff08;一&#xff09;知识图谱的特征及功能 知识图谱是为了适应新的网络信息环境而产生的一种语义知识组织和服务的方…

WRT1900ACS搭建openwrt服务器小记

参考链接 wrt1900acs openwrt wrt1900acs openwrt 刷机 wrt1900acs原生固件刷openwrt-23.05.3-mvebu-cortexa9-linksys_wrt1900acs-squashfs-factory.img wrt1900acs openwrt更新刷openwrt-23.05.3-mvebu-cortexa9-linksys_wrt1900acs-squashfs-sysupgrade.bin 通过WEB UI来…

linux的信号量的使用

1.信号量 在多线程情况下&#xff0c;线程要进入关键代码就得获取信号量&#xff08;钥匙&#xff09;{sem_init(&sem, 0, 0);}&#xff0c;没有信号量的情况下就一直等待sem_wait(&sem)&#xff0c;只到别人把钥匙&#xff08;sem_post(&sem)&#xff09;给你。 …

从哪些方面可以看出现货黄金价格走势?

现货黄金价格的走势受到多种因素的影响&#xff0c;我们可以从宏观经济环境、货币政策、供需关系、市场情绪和技术分析几个主要方面来观察和分析这一贵金属的价格动态。现货黄金作为全球投资市场中的避险资产&#xff0c;其价格波动往往能体现出复杂的经济和政治变化。 宏观经济…