详解JAVA类加载器
目录
1.概述
2.双亲委派
3.ServiceClassLoader
4.URLClassLoader
5.加载冲突
1.概述
概念:
类加载器(Class Loader)是Java虚拟机(JVM)的一个重要组件,负责加载Java类到内存中并使其可以被JVM执行。类加载器是Java程序的核心机制之一。
分类:
类加载器一共有三种:
- 启动类加载器,加载系统类rt.jar。
- 扩展类加载器,加载JDK内部,rt.jar之外,由于JDK版本迭代而新出现的扩展类。
- 应用类加载器加载J用户所配置的classpath下的类。
三种类加载器之间从上到下有父子关系,上层是下层的父加载器。

2.双亲委派
在类加载中可能会遇见这样一种情况:
JDK里自带一个java.lang.String,有一个恶意的攻击类也将类的全类名命名为java.lang.String。如果我们想使用String类型的时候,类加载器将这个伪装成JDK的String类的恶意类加载执行,系统就将遭受到破坏。
很明显,为了安全起见JDK需要一种合理的加载方式来控制类的加载,这种合理的加载方式就是——双亲委派机制。
双亲委派机制总结起来就是:
先找父级加载器要,要是父级加载器没有,再由自己加载。
因为启动类加载器、扩展类加载器工作在应用的启动阶段,加载的也是JDK内核相关的jar,与应用没有太大关系,与应用相关的只有应用程序加载类,而应用程序的父级最多也就是扩展类加载器、启动类加载器,也就是最多找两个双亲拿,所以称为双亲委派机制。
整个类加载的详细流程为:
我们来看看任意一个ClassLoader的loadClass源码,整个源码中双亲委派的体现很直接:

类加载器在需要加载一个类(class)的时候会先判断类是否被自己加载过,
如果没有,调用其成员变量classloader parent委托其父载器帮忙加载,
父加载器再重复以上过程,如果递归到最顶级的启动类加载器,发现都加载不了,
当前启动器会自行加载。
3.ServiceClassLoader
SPI机制:
SPI(Service Provider Interface),是在JDK1.6中提出的一种基于接口的服务发现机制,它允许第三方服务提供者扩展框架的功能。在SPI机制中,框架定义一组接口,并规定这些接口的实现类必须以一定的命名规则放在特定的路径下,然后通过Java自带的SPI机制,动态地加载和实例化这些实现类。
基于SPI机制可以实现这样的生态结构,由官方制定一些标准,厂商去给出实现,也就是官方给出接口,由各大厂商去实现接口,如JAVA EE规范中的JDBC规范等等,支撑SPI实现的核心是一个类加载器——ServiceClassLoader。

ServiceClassLoader是一种用于加载和实例化服务提供者的工具类。服务提供者是指实现了特定接口或抽象类的类,而服务加载器则负责在运行时动态地查找和加载这些实现类。
-
定义服务接口:定义一个Java接口或抽象类,用于描述服务提供者必须实现的行为。
-
实现服务提供者:定义一个或多个服务提供者,实现服务接口或抽象类。
-
配置服务提供者:在META-INF/services目录下创建一个以服务接口或抽象类名为文件名的文件,并在文件中列出所有实现服务接口或抽象类的类名。
-
加载服务提供者:使用Service Loader类动态加载和实例化服务提供者。
代码示例:
接口:
package com.eryi;public interface HelloService {void sayHello();
}
实现类:
package com.eryi;public class ChineseHelloService implements HelloService{@Overridepublic void sayHello() {System.out.println("你好!");}
}
package com.eryi;public class EnglishHelloService implements HelloService{@Overridepublic void sayHello() {System.out.println("Hello!");}
}
发布服务:
在META-INF/services目录下创建一个名为"com.eryi.HelloService"的文件,文件内容如下:
com.eryi.EnglishHelloService
com.eryi.ChineseHelloService
服务发现:
package com.eryi;import java.util.ServiceLoader;public class test {public static void main(String[] args) {ServiceLoader<HelloService> loader = ServiceLoader.load(HelloService.class);for (HelloService service : loader) {service.sayHello();}}
}
运行结果:

4.URLClassLoader
启动类加载器、扩展类加载器、应用类加载器均是在程序工作之前完成对各个路径下所有jar包的加载的,这些路径里的jar包后续如果有什么变化,这三个类加载器是无法进行加载从而动态进行更新的。URLClassLoader就是为了实现这种动态加载而出现的。
URLClassLoader支持三种路径:
-
目录
-
jar包
-
网络
代码示例:
public class test {public static void main(String[] args) throws Exception {// 创建一个URLClassLoader,指定加载路径为当前目录URLClassLoader classLoader = new URLClassLoader(new URL[] { new URL("file:./") });// 动态加载HelloWorld类Class<?> helloWorldClass = classLoader.loadClass("HelloWorld");// 创建HelloWorld对象Object helloWorld = helloWorldClass.newInstance();// 调用HelloWorld对象的sayHello方法helloWorldClass.getMethod("sayHello").invoke(helloWorld);}
}class HelloWorld {public void sayHello() {System.out.println("Hello, world!");}
}
由于URLClassLoader具有动态加载的特性,所以很适合拿来做热部署。
5.加载冲突
同一个类被不同加载器加载,加载结果视为两个不同类。
所以在加载之前需要判断是否被加载,如果未加载,则遵循双亲委托模型,从而避免加载冲突。
代码示例:
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;public class Main {public static void main(String[] args) throws Exception {// 创建两个不同的URLClassLoader,分别加载同一个类URL[] classpath = { new File("classes/").toURI().toURL() };URLClassLoader classLoader1 = new URLClassLoader(classpath);URLClassLoader classLoader2 = new URLClassLoader(classpath);// 使用classLoader1加载HelloWorld类Class<?> helloWorldClass1 = classLoader1.loadClass("HelloWorld");// 使用classLoader2加载HelloWorld类Class<?> helloWorldClass2 = classLoader2.loadClass("HelloWorld");// 输出两个类是否相同System.out.println(helloWorldClass1 == helloWorldClass2); // false}
}class HelloWorld {public void sayHello() {System.out.println("Hello, world!");}
}
相关文章:
详解JAVA类加载器
目录 1.概述 2.双亲委派 3.ServiceClassLoader 4.URLClassLoader 5.加载冲突 1.概述 概念: 类加载器(Class Loader)是Java虚拟机(JVM)的一个重要组件,负责加载Java类到内存中并使其可以被JVM执行。类…...
记录一些常用C标准库函数,以及Linux系统调用函数的作用(不断更新)
C标准库函数 perror() 函数 作用:perror函数是C标准库中的一种函数,用于在STDERR(标准错误输出流)中输出给定的错误信息字符串。它不属于Linux系统调用函数。 具体使用方法:perror("调用的函数名") 所需…...
RK3568平台开发系列讲解(显示篇)DRM的atomic接口
🚀返回专栏总目录 文章目录 一、Property二、Standard Properties三、代码案例沉淀、分享、成长,让自己和他人都能有所收获!😄 📢目前DRM主要推荐使用的是 Atomic(原子的) 接口。 一、Property Property(属性)—– Atomic操作必须依赖的基本元素 Property把前面的…...
2022年MathorCup数学建模C题自动泊车问题解题全过程文档加程序
2022年第十二届MathorCup高校数学建模 C题 自动泊车问题 原题再现 自动泊车是自动驾驶技术中落地最多的场景之一,自动泊车指在停车场内实现汽车的自动泊车入位过程,在停车空间有限的大城市,是一个比较实用的功能,减少了驾驶员将…...
【需求响应】基于数据驱动的需求响应优化及预测研究(Matlab代码实现)
👨🎓个人主页:研学社的博客💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密…...
Bellman-ford和SPFA算法
目录 一、前言 二、Bellman-ford算法 1、算法思想 2、算法复杂度 3、判断负圈 4、出差(2022第十三届国赛,lanqiaoOJ题号2194) 三、SPFA算法:改进的Bellman-Ford 1、随机数据下的最短路问题(lanqiaoOJ题号1366&…...
假如你知道这样的MySQL
数据库三范式是什么? 第一范式(1NF):字段具有原子性,不可再分。(所有关系型数据库系 统都满足第一范式数据库表中的字段都是单一属性的,不可再分)第二范式(2NF)是在第一范式(1NF)的…...
SpringBoot笔记(一)入门使用
一、为什么用SpringBootSpringBoot优点创建独立Spring应用内嵌web服务器自动starter依赖,简化构建配置自动配置Spring以及第三方功能提供生产级别的监控、健康检查及外部化配置无代码生成、无需编写XMLSpringBoot缺点人称版本帝,迭代快,需要时…...
C++20 协程体验
1 介绍协程是比线程更加轻量级并发编程方式,CPU资源在用户态进行切换,CPU切换信息在用户态保存。协程完成异步的调用流程,并对用户展示出同步的使用方式。协程的调度由应用层决定,所以不同的实现会有不同的调度方式,调度策略比较灵…...
这三个小事你做HIGG FEM时要知道
【这三个小事你做HIGG FEM时要知道】1.为什么做了Higg FEM 自评后要做验证?「自评 验证」Higg FEM 是一个持续改善的框架方法,来帮助工厂实现持续的环保改善,是一个最基本的要求,如果工厂期望得到一个更加客观的评价,…...
.net6 wpf程序一个内存不断增长问题的解决方法
一个.net6的应用程序,底层不断采集数据。使用wpf制作了一个简单的界面显示数据接收的情况。程序中引用了 Material Design UI框架。当程序长时间运行时发现内存在不断增长。一个星期后工作集占用内存达到1GB。使用dotnet-dump工具收集内存使用情况,并且分…...
NICEGUI---ROS开发之中常用的GUI工具
0. 简介 对于ROS来说,如果不具备一定知识的人员来使用这些我们写的算法,如果说没有交互,这会让用户使用困难,所以我们需要使用GUI来完成友善的数据交互,传统的GUI方法一般有PYQT这类GUI方法,但是这类GUI工…...
高盐废水除钙镁的技术解析
高盐废水指含有机物和至少总溶解固体(totaldissolvedsolids,tds)的质量分数大于3.5%的废水,具有水量大,无机盐离子k、na、ca2、mg2、cl-、so42-等含量高,水质水量变化大,成分复杂,难生化降解等特…...
回文日期门牌制作
题目: 题目描述 如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。 给定一个 8 位数的日期,请…...
基于半车悬架的轴距预瞄与轴间预瞄仿真对比
目录 前言 1. 半车悬架模型 2.轴距预瞄(单点预瞄)和轴间预瞄(两点预瞄)原理与仿真分析 2.1轴距预瞄(单点预瞄) 2.1.1预瞄原理 2.2.轴间预瞄(两点预瞄) 2.2.1预瞄原理 2.3仿真分析 3.总结 前言 对于悬架而言,四个车轮实际的输入信息是受到前后延时以及左右相…...
Linux开发 安装JDK8、p4
前面的笔记: Linux 学习笔记1 安装linux详细教程_linux系统 setting_O丶ne丨柒夜的博客-CSDN博客 Linux 学习笔记2 常用命令_O丶ne丨柒夜的博客-CSDN博客 Linux 学习笔记3 权限管理 定时任务 网络配置_O丶ne丨柒夜的博客-CSDN博客 安装配置 安装配置JDK8 Java …...
基于 x86 SoC 的车辆智能驾驶舱和ADAS设计(一)
随着汽车成为软件定义的自动化领域的中心,英特尔致力于提供从汽车到云的可扩展安 全解决方案来加快从高级驾驶员辅助系统(ADAS)到全自动汽车为自动驾驶提供技术支持。 2016 年 3 月,英特尔斥资 153 亿美元收购了以色列高级辅助驾驶系统企业 Mobileye。20…...
类模板函数模板
准备看个项目找实习,边看边学,一看到处都是template 和typename,好几年前学的C都忘记光了,在这里先做个笔记复习一下。template <class T> T abs(T x) {if(x < 0) return -x;return x; } int main() {int x 1;cout <…...
Leetcode DAY 56: 两个字符串的删除操作 and 编辑距离
583. 两个字符串的删除操作 1 、 dp[i][j] 表示 让以word1[i - 1]为结尾的字符串 和 以word2[i - 2]为结尾的字符串 相等需要删除的最少次数 1、dp[i][j] 的 递推需要考虑两种情况: (1)word1[i - 1] word2[j - 1] 相当于不考虑word1[i]和…...
系统检测维护工具Wsycheck使用(18)
实验目的 (1)学习Wsycheck的基本功能; (2)掌握Wsycheck的基本使用方法; 预备知识 windows操作系统的基本知识如:进程、网络、服务和文件等的了解。 Wsycheck是一款强大的系统检测维护工具,进程和…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
Vue3中的computer和watch
computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
如何做好一份技术文档?从规划到实践的完整指南
如何做好一份技术文档?从规划到实践的完整指南 🌟 嗨,我是IRpickstars! 🌌 总有一行代码,能点亮万千星辰。 🔍 在技术的宇宙中,我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...
初级程序员入门指南
初级程序员入门指南 在数字化浪潮中,编程已然成为极具价值的技能。对于渴望踏入程序员行列的新手而言,明晰入门路径与必备知识是开启征程的关键。本文将为初级程序员提供全面的入门指引。 一、明确学习方向 (一)编程语言抉择 编…...
