JVM面试(四)类加载器和双亲委派机制

什么是类加载器?

简单来说的话,是用于实现“类加载动作”的加载器
“通过一个类的全限定名来获取描述该类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需的类。实现这个动作的代码被称为“类加载器”(Class Loader)。

这里需要注意一个特点,对于任何一个类,都要根据这个类本身以及加载它的类加载器来共同确认其在Java虚拟机中的唯一性
有些拗口,但是希望各位同学能多念几遍理解一下。

从另一个角度来说,如果两类的名字相等,即使来自同一个.class文件,但是所用的类加载器不是同一个,虚拟机就不会认为是同一个类,是两个独立的类。

为什么需要双亲委派机制?

上面说了,不同类加载器加载出来的类,一定不相同。

所以,为了保护java底层本身的类不被篡改(比如java.lang.Object、java.lang.String)。
无论是在各种程序中,各种类加载器环境中都保证被同一个类加载器进行加载。
就是用双亲委派机制,全都委派给处于模型最顶端的启动类加载器进行加载。
如下图:
在这里插入图片描述

双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。

其实代码也简单得很,如下:

protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{// 首先,检查请求的类是否已经被加载过了Class c = findLoadedClass(name);if (c == null) {try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// 如果父类加载器抛出ClassNotFoundException// 说明父类加载器无法完成加载请求}if (c == null) {// 在父类加载器无法加载时// 再调用本身的findClass方法来进行类加载c = findClass(name);}}if (resolve) {resolveClass(c);}return c;
}

破坏双亲委派机制

很好理解啊,加载类的时候不按照这个顺序APPClassLoader->Ext ClassLoader->BootStrap ClassLoader进行加载就算是打破了双亲委派机制呗。

比如tomcat,只要用过tomcat部署工程的都知道,我们是把项目打成war包,让在webapp文件夹下面,那么就意味着tomcat同时可以运行多个web程序。

那在多个项目里面就有可能存在相同名称和路径的类。为了防止他们不冲突,tomcat就给每个web应用都创建一个类加载器实例,WebAppClassLoader。
该类重写了loaderClass()方法,优先加载当前应用目录下的类,如果找不到了,再进入用双亲委派机制一层层寻找加载器。
这其实算是一个双亲委派机制的补丁。

还有一种情况,双亲委派机制本身的模型就是“越基础的类,越由上层加载器来加载”。 那么什么是“基础”类? 就是哪些总作为被继承、调用API存在的类。 但是,如果存在那种,既有基础类型,又要回调用户代码怎么办?

这里最典型的就是JDBC,JDBC定义类接口,但是实现类肯定是由各个厂商来实现的, 比如mysql。
我们使用jdbc的时候,通过DriverManager来获取connection链接的,明显DriverManager是基础类,由BootstrapClassLoader加载的。

但是在我们使用DriverManager.getConnection()的时候,获取的一定是数据库厂商的类,BootstrapClassLoader不可能加载到第三方厂商的类啊。
解决方案就是,DriverManager在初始化的时候获取「线程上下文加载器」(Thread Context ClassLoader),在获取connection的时候使用线程上下文加载器来加载connection,这里的线程上下文加载器实际上还是App ClassLoader。
所以在获取connection的时候先找ExtClassLoader和BootstrapClassLoader加载器,只不过这俩加载器肯定加载不到,最终还是由AppClassLoader来加载。

其实话说回来,这些也可以算作双亲委派机制的加强补丁,并不是“破坏”双亲委派机制。 仁者见仁智者见智吧

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

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

相关文章

Ollama拉起本地模型以及rag系统部署。

什么是 Ollama &#xff1f; Ollama 是一个简明易用的本地大模型运行框架。能在本地启动并运行 Llama、qwen、Gemma 及其他大语言模型&#xff0c;没有GPU资源照样可以拉起模型&#xff0c;和LocalAI 比较类似&#xff0c;但是加载模型更容易。 1.安装 安装后运行&#xff0c…

解剖学上合理的分割:通过先验变形显式保持拓扑结构|文献速递--基于深度学习的医学影像病灶分割

Title 题目 Anatomically plausible segmentations: Explicitly preserving topology through prior deformations 解剖学上合理的分割&#xff1a;通过先验变形显式保持拓扑结构 01 文献速递介绍 进行环向应变或壁厚度的计算&#xff0c;这些测量通常用于诊断肥厚性心肌病…

Vue前端路由详解——以Ruoyi框架为案例学习

Vue路由 Vue路由详解_vue 页面路由-CSDN博客 路由模式 Vue 的路由模式&#xff1a;hash 模式和 history 模式的区别_vue路由history和hash的区别-CSDN博客 URL格式&#xff1a; Hash模式&#xff1a;URL中包含#号&#xff0c;用于区分页面部分&#xff0c;实际请求的页面地址…

【深度学习与NLP】——词嵌入Embedding技术

目录 1.词嵌入的作用 2.嵌入矩阵的计算 3.Embedding层的代码实验 词嵌入&#xff08;Embedding&#xff09;技术是一种将词汇映射到低维连续向量空间的方法。将离散的单词数据处理成连续且固定长度的向量&#xff0c;使模型可以学习和处理语义信息。 假设需要将["Are&…

【MySQL00】【 杂七杂八】

文章目录 一、前言二、MySQL 文件1. 参数文件2. 日志文件3. 套接字文件4. pid 文件5. 表结构定义文件6. InnoDB 存储引擎文件 二、BTree 索引排序三、InnoDB 关键特性1. 插入缓冲1.1 Insert Buffer 和 Change Buffer1.1 缓冲合并 2. 两次写2. 自适应哈希索引3. 异步IO4. 刷新邻…

关于武汉芯景科技有限公司的A/D转换芯片XJ3021开发指南(兼容MCP3021)

一、芯片引脚介绍 1.芯片引脚 2.引脚描述 二、系统结构图 三、时序&#xff08;IIC通信&#xff09; 四、程序代码 XJ3021.C /** XJ3021.c** Created on: 2024年8月23日* Author: Administrator*/ #include "softiic.h" #include "XJ3021.h" #inc…

《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 09部署OSPF

本章的目的是帮助网络工程师确定网络的理想 OSPF 配置。本章将回答以下问题 应何时在数据中使用OSPF ?配置 OSPF 的关键设计原则是什么?OSPFv2 和 OSPFv3 之间有什么区别&#xff0c;应如何使用?如何在路由协议栈中配置 OSPF ?如何在服务器上配置 OSPF&#xff0c;例如为容…

【MySQL08】【死锁】

文章目录 一、前言二、查看事务加锁情况1. 使用 information_schema 数据库中表获取锁信息1.1 INNODB_TRX1.2 INNODB_LOCKS1.3 INNODB_LOCK_WAITS 2. 使用 SHOW ENGIN INNODB STATUS 获取锁信息 三、死锁四、参考内容 一、前言 最近在读《MySQL 是怎样运行的》、《MySQL技术内…

Android之Handler的post方法和sendMessage的区别

目录 post 方法方法特点 sendMessage 方法方法特点 使用场景区别总结 Handler 类在 Android 中用于在不同线程之间传递消息和执行代码。它提供了两种主要的方式来执行任务&#xff1a;通过 post 方法和通过 sendMessage 方法。这两种方法有不同的使用场景和特点。 post 方法 方…

浅谈架构实战

目录 背景 1 架构演变 2 如何实现高层的复用 2 中台产生案例 3 技术架构的核心要点 4 技术架构的高可用案例 背景 业务架构、数据架构、应用架构和技术架构它们是相互关联和相互支持的&#xff0c;共同构成了企业的总体架构&#xff0c;业务架构是源头&#xff0c;然后才…

自动生成对话视频!如何使用Captions的AI视频生成与编辑API工具?

Captions公司最近发布了一套AI驱动的视频生成和编辑API工具&#xff0c;为创作者和开发者提供了一个强大的视频创作生态系统。这个系统包含AI Creator、AI Twin、AI Edit、和AI Translate四大核心功能&#xff0c;每个工具都针对不同的创作需求进行优化。下面我们就一起来详细测…

第九周:机器学习

目录 摘要 Abstract 一、RNN 1、引入 2、RNN的分类 二、LSTM 1、基本结构 2、具体步骤 3、举例说明 4、原理理解 总结 摘要 本周主要围绕RNN进行探讨&#xff0c;从为什么需要这类”循环网络“入手&#xff0c;提到了”slot filling“技术&#xff0c;接着又对R…

AT3340:支持BDS/GPS双模授时板数据手册

AT3340采用ATGM331C-5T31授时模块&#xff0c;是高授时精度的BDS/GPS双模接收机板卡&#xff0c;包含32个跟踪通道&#xff0c;支持GPS和BDS的单系统授时定位和双系统联合授时定位&#xff0c;可以通过上位机命令切换。其中的射频前端芯片和基带芯片全部由杭州中科微独立研发&a…

RAG数据集自动构造探索, 附prompt

从文档中手动创建数百个 QA&#xff08;问题-上下文-答案&#xff09;样本可能非常耗时且劳动密集。此外&#xff0c;人工生成的问题可能难以达到全面评估所需的复杂程度&#xff0c;最终影响评估的质量。通过使用合成数据生成&#xff0c;开发人员在数据聚合过程中的时间可以减…

嵌入式Linux:常见信号的默认行为

信号是一种软件中断&#xff0c;用于通知进程发生了某种异步事件。信号可以由用户、其他进程或操作系统内核产生。进程可以选择捕获并处理这些信号&#xff0c;或者忽略它们&#xff0c;让系统执行默认操作。 不可靠信号&#xff08;非实时信号&#xff09;&#xff1a;编号为 …

观测云核心技术解密:eBPF Tracing 实现原理

前言 eBPF 是一种强大的内核技术&#xff0c;允许在内核中安全地执行自定义代码。通过 eBPF&#xff0c;开发者可以在不修改内核源码的情况下&#xff0c;对内核功能进行扩展和监控。eBPF Tracing 利用这一技术&#xff0c;对系统调用、内核函数等进行跟踪&#xff0c;从而实现…

【IPV6从入门到起飞】2-1 获取你的IPV6(手机、CPE等)

【IPV6从入门到起飞】2-1 获取你的IPV6&#xff08;手机、CPE等&#xff09; 1 IPV6就在身边2 手机IPV62.1 查看IPV62.2 IPV6 ping包测试2.3 IPV6入站测试 3 电脑通过CPE获取IPV63.1 拉不起宽带的打工人3.2 开始部署IPV6环境3.2.1 刷系统3.2.2 激活IPV63.2.3 设置防火墙入站&am…

JAVA - 关于防重复提交探讨

1、前端提交按钮做单次点击 2、后端接收判断请求的数据包&#xff0c;生成唯一key存redis&#xff0c;设置几秒的过期时间&#xff08;缺陷&#xff1a;带时间戳的数据&#xff0c;需要做些逻辑判断&#xff09; 3、后端代码逻辑redis分布式锁&#xff08;缺陷&#xff1a;re…

P01-Java何谓数组

P01-Java何谓数组 一、数组声明创建 1.1 数组声明的语法 与c有所不同 在Java中&#xff0c;数组声明语法 首选语法&#xff1a; //数据类型[] 数组名称; int[] arr;次选&#xff0c;与c类似 //数据类型 数组名称[]; int arr[];1.2 数组创建语法 与c指针有所相似&#xff0…