【java 基础】闲话 ClassLoader 和 SPI (一)

文章目录

    • 引子
    • 双亲委派模型
      • 你真的明白了吗?
    • 双亲委派“不够用了”
      • SPI机制
    • 其他琐碎

引子

有别于 java 提供的 IO 模块,java 中的classloader主要是用来加载类的,当然除了加载类,也可以加载资源文件。

那么首先我们会问一个问题,有了 IO 为什么要 classloader?这是我们开启 classloader 大门要弄明白的第一个问题。

java IO 提供了一些常见的功能,比如读文件、写文件,操作字符流、字节流,网络的读写,文件系统操作等等功能,不胜枚举。显而易见,java IO 提供了一些通用方法。

而 classloader 是 JVM 用来按需动态加载资源的工具。之所以有 classloader 有多方面的考虑,首先要解决程序运行时怎么加载类,需要一套机制,这套机制就是我们常说的双亲委派模型。其次是怎么读取资源,比如我们想要读取某个配置文件,或者一张图片(当然读取资源文件我们可以直接用 IO 也不是不可以,殊途同归)。

双亲委派模型

老生常谈的话题,不过也值得讨论一番。java 内建的classloader主要分为 3 类:

  • Bootstrap ClassLoader
  • Extension ClassLoader(又叫 Platform ClassLoader)
  • Application ClassLoader(又叫 System ClassLoader)

Bootstrap ClassLoader: 是最顶层的ClassLoader,负责加载JRE核心库,它是用C++实现的,无法通过Java代码来创建。
Extension ClassLoader:负责加载Java的扩展库。(本质上还是 java 官方提供的,由 java 实现的类库)
Application ClassLoader:负责加载用户类路径下的类。比如我们自己编写的类,引入的第三方 jar 包等。

如下图:我们举一个例子,假设 JVM 要加载类 A,首先会通过 Application ClassLoader 进行加载,这时首先检查其缓存中是否已加载此类,如果加载,则返回。如果缓存中没有类 A,则委托给 Extension ClassLoader进行加载,同样是先检查是否有缓存,如果没有则委托给 Bootstrap ClassLoader 进行加载,同样是检查缓存,如果还是没有,则尝试扫描 JRE 核心库是否有该类,如果有,则加载类,否则返回到 Extension ClassLoader,Extension ClassLoader 扫描其负责的扩展库,如果有,则加载,否则返回到 Application ClassLoader进行加载,Application ClassLoader扫描用户的类路径,如果找到该类,则加载,否则则抛出ClassNotFound 异常。
Image: https://uploader.shimo.im/f/XticuP44pZvBeor5.png!thumbnail?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MDkyNzg0NzUsImZpbGVHVUlEIjoiNXhrR29HeEVqT0N6MXprWCIsImlhdCI6MTcwOTI3ODE3NSwiaXNzIjoidXBsb2FkZXJfYWNjZXNzX3Jlc291cmNlIiwidXNlcklkIjo5NDQ4NDE4fQ.7teiXi8UKNQMlxXtA9Puy-Q_HJAeV0kRoqqgjO3qs8k

你真的明白了吗?

回答下面这个问题:如果类 A 是 Extension ClassLoader 加载,而类 A 中又引入了类 B,那么类 B 会怎么被加载呢?还是从 Appcation ClassLoader 开始加载吗?

答案是否定的,类 B 会从 Extension ClassLoader 开始加载,先委托Bootstrap ClassLoader,如果没找到,则 Extension ClassLoader自己开始加载,如果找不到,则抛出 ClassNotFound,并不会再返回到 Application ClassLoader 进行加载。为什么要这样设计?很简单,留给大家自己思考吧。

双亲委派“不够用了”

有时候默认的双亲委派不够用,举个例子,java 定义了一个数据库标准接口 JDBC,各个数据库厂商会实现这个标准接口,即我们所说的数据库驱动包。大家在学JDBC 的时候应该都写过类似这种代码

Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbName");

大家可以尝试将第一句删除掉,你会发现还是可以获取到Connection,这是为什么呢?DriverManager的包名是 java.sql,显然是 jdk的核心包,所以定然不会在其中写入加载某个具体驱动类的代码。所以 java 的开发人员就发明了一种新的方法:SPI(Service Provider Interface)

SPI机制

SPI 的机制很简单,我们还是以数据库驱动为例,首先各个驱动厂商开发对应的驱动包,不过动包会有些特殊,如下图:
在这里插入图片描述
在驱动包的 META-INF/services 下会包含与所要实现驱动名称相同的一个文本文件,文本文件的内容是实现这个驱动的具体类。

然后在执行 DriverManager.getConnection("jdbc:mysql://localhost:3306/dbName");时有以下代码:
Image: https://uploader.shimo.im/f/j7jalpGRyOGJ0Ghs.png!thumbnail?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjE3MDkyNzg0NzUsImZpbGVHVUlEIjoiNXhrR29HeEVqT0N6MXprWCIsImlhdCI6MTcwOTI3ODE3NSwiaXNzIjoidXBsb2FkZXJfYWNjZXNzX3Jlc291cmNlIiwidXNlcklkIjo5NDQ4NDE4fQ.7teiXi8UKNQMlxXtA9Puy-Q_HJAeV0kRoqqgjO3qs8k
通过 ServiceLoader.load(Driver.class)去加载驱动。具体怎么加载这里就不说了,无非是扫描上面我们说的META-INF/services目录下的文件,将所有实现了Driver接口的驱动都注册进来。那为什么这里就可以加载到了呢?因为我们在执行ServiceLoader.load(Driver.class)方法时,方法内部是通过 Application ClassLoader 进行加载的,自然可以加载到外部的驱动包了。

那么,如果我引入了多个驱动包呢?系统怎么知道我们用的哪一个?如下图,在 Driver 接口中定义了一个方法:acceptsURL,通过对jdbc:mysql://localhost:3306/dbName这种格式的判断来决定此驱动是不是用户想要的驱动。

在这里插入图片描述
DriverManager 中调用上面实现的acceptsURL 方法:
在这里插入图片描述

其他琐碎

说了那么多,好像跟我们自己平常开发没有多少关系。其实我们也可以利用ClassLoader来加载起源,比如我们想读取一个配置文件。可以用类似ClassLoader.findResource("xxx")或者this.class.getResource("xx")。在一些代码里我们还会看到:ClassLoader cl = Thread.currentThread().getContextClassLoader();这样的代码,这些是在干嘛?后续再跟大家唠唠吧。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

光伏业务管理软件有哪些推荐?

光伏业务管理软件是用于光伏电站的设计、施工、运营和维护等各个环节的软件工具。以下是一些推荐的光伏业务管理软件: PVsyst 这是一款全球广泛使用的光伏系统设计软件,可以进行详细的系统设计,包括组件匹配、逆变器选择、系统布局等。 鹧…

电子信息行业数字化转型创新应用挑战赛火热进行中,速戳

由深圳市宝安区人民政府、中国信息通信研究院联合举办的“第七届工业互联网数据创新应用大赛——解决方案赛道:电子信息行业数字化转型创新应用挑战赛”火热进行中!大赛报名时间截至2024年3月15日,并将于3月25日在深圳宝安进行线下决赛答辩。…

如何辨别GPT3还是GPT4?

辨别后台使用的是GPT3还是GPT4可以提问以下问题验证: 1.昨天的当天的明天是哪天? 2.树上有9只鸟,猎人射杀了一只,还剩下多少只? 3.为什么周树人要打鲁迅? GPT3回答: GPT4回答: 如…

全闪存加速信创数据库数仓一体机解决方案

立足行业,深度解读 在新的大数据生态中,传统数据库/数据仓库技术和产品成为大数据生态中的组成部分,对结构化数据的存储和计算进行支撑。 数据库&数据仓库一体机是高端、核心数据管理产品,在我国党政、银行、交通等领域广泛…

市场热点袭来,直接加仓可靠吗?九方智投洪帮主助投资者明确几大要点

消费电子近期再度走强,多企业均出现涨停。消费电子出现乐观局面,有投资者认为是因为目前市场需求旺盛,产业链正在积极拉货,持续加单,各类手机新机也在积极备货,消费电子库存低。面对市场情绪高涨&#xff0…

LabVIEW最佳传输系统设计

LabVIEW最佳传输系统设计 介绍了基于LabVIEW软件开发的最佳基带传输系统和最佳带通传输系统的设计。通过软件仿真实现了脉冲成形滤波器和匹配滤波器的设计,证明了系统在消除码间干扰和抗噪声方面的优异性能。此设计不仅激发了学生的学习兴趣,还有助于提…

AI智能分析网关V4车辆违停算法在园区场景中的应用及特点

随着城市化进程的加速,车辆违停问题愈发严重,给城市交通带来了极大的困扰。为了解决这一问题,AI技术逐渐被应用于车辆违停的检测中。AI检测算法在车辆违停方面的应用,主要是通过计算机视觉技术,对道路上的车辆进行实时…

nodejs配置环境变量后不生效(‘node‘ 不是内部或外部命令,也不是可运行的程序或批处理文件)

一、在我们安装Node.js后,有时候会遇到node命令不管用的情况,关键是在安装时候已经添加配置了环境变量,向下面这样 但是还是不管用,这是因为环境变量配置不正确,权重不够,或者是命令冲突导致,解…

人工智能驱动的自拍时代:短视频美颜SDK技术的发展趋势

在短视频自拍的过程中,美颜技术的应用已经成为了许多人的必备工具,其中短视频美颜SDK技术的发展更是推动了自拍时代的进步。 1.人工智能技术的崛起 传统的美颜功能主要是通过简单的图像处理和滤镜效果来实现,但是这种方法往往会导致照片失真…

【Java】UWB高精度工业定位系统项目源代码

目录 UWB技术原理 优势 1. 高精度: 2. 抗干扰能力强: 3. 定位范围广: 4. 实时性强: 应用前景 定位系统源码功能介绍 实时定位: 轨迹回放: 区域管理: 巡检管理: 数据可视化分析&…

【ArcPy】批量读取文件夹excel中XY并转为点shp

示例展示 代码 只读取excel中含有XY字段的文件,并将矢量命名为excel文件名称。 import os import pandas as pd import arcpy folder_path r"C:\Users\admin\Desktop\excelfile" extension"xlsx" files [file for file in os.listdir(folder…

Prometheus(二):NodeExporter和Grafana的安装和使用

目录 1 Node Exporter安装1.1 简介1.2 安装1.3 Prometheus收集node_exporter数据 2 安装Grafana2.1 安装2.2 使用1、创建数据源2、选择模板3、模板导入 2.3 grafana创建用户1、创建用户2、验证 总结 1 Node Exporter安装 1.1 简介 node exporter是Prometheus的收集数据的组件…

使用 WordPress SureMembers 创建 Patreon 等粉丝网站

各行各业的创意专业人士和爱好者越来越多地转向在线平台分享他们的作品、建立忠实的粉丝并创造收入。 无论您是新晋艺术家还是知名影响者,拥有粉丝订阅网站都可以帮助您将热情货币化,同时培养紧密的支持者社区。 根据Statista的一份报告,到…

商城系统_大型商城系统源码_免费开源商城_OctShop

随着互联网对各行各业的渗透,以及人们网络购物的习惯已经形成,很多商家或企业都开始搭建与开发自己的商城系统平台。商城系统是一个以互联网技术为基础,依托电子商务的电商系统平台。一般大型的的商城系统都会有前台各种客户端,如…

【手机端测试】adb基础命令

一、什么是adb adb(Android Debug Bridge)是android sdk的一个工具 adb是用来连接安卓手机和PC端的桥梁,要有adb作为二者之间的维系,才能让用户在电脑上对手机进行全面的操作。 Android的初衷是用adb这样的一个工具来协助开发人…

PoC免写攻略

在网络安全领域,PoC(Proof of Concept)起着重要的作用,并且在安全研究、漏洞发现和漏洞利用等方面具有重要的地位。攻击方视角下,常常需要围绕 PoC 做的大量的工作。常常需要从手动测试开始编写 PoC,再到实…

【数仓】Hadoop软件安装及使用(集群配置)

一、环境准备 1、准备3台虚拟机 Hadoop131:192.168.56.131Hadoop132:192.168.56.132Hadoop133:192.168.56.133 本例系统版本 CentOS-7.8,已安装jdk1.8 2、hosts配置,关闭防火墙 vi /etc/hosts添加如下内容&#x…

【软考高项】【计算专题】- 5 - 进度类 - 横道图/甘特图

一、知识点 1、基本定义 甘特图(Gantt chart )又称为横道图、条状图(Bar chart),通过条状图来显示项目各活动的进 度情况。以提出者亨利劳伦斯甘特( Henry Laurence Gantt)先生的名字命名。 目前许多文档工具都可以画甘特图。 (1)我的举例 …

Linux进程 | 环境变量 | 程序地址空间

基本概念 课本概念:程序的一个执行实例,正在执行的程序等内核观点:担当分配系统资源(CPU时间,内存)的实体。 描述进程-PCB 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的…

鸿蒙Harmony应用开发—ArkTS声明式开发(按键事件)

按键事件指组件与键盘、遥控器等按键设备交互时触发的事件,适用于所有可获焦组件,例如Button。对于Text,Image等默认不可获焦的组件,可以设置focusable属性为true后使用按键事件。 说明: 从API Version 7开始支持。后续…