JVM——类加载器
回顾一下类加载过程
类加载过程:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析。

一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以去完成还可以自定义类加载器去控制字节流的获取方式(重写一个类加载器的 loadClass() 方法)。数组类型不通过类加载器创建,它由 Java 虚拟机直接创建。
所有的类都由类加载器加载,加载的作用就是将 .class文件加载到内存。
类加载器总结
JVM 中内置了三个重要的 ClassLoader,除了 BootstrapClassLoader 其他类加载器均由 Java 实现且全部继承自java.lang.ClassLoader:
- BootstrapClassLoader(启动类加载器) :最顶层的加载类,由C++实现,负责加载
%JAVA_HOME%/lib目录下的jar包和类或者或被-Xbootclasspath参数指定的路径中的所有类。 - ExtensionClassLoader(扩展类加载器) :主要负责加载目录
%JRE_HOME%/lib/ext目录下的jar包和类,或被java.ext.dirs系统变量所指定的路径下的jar包。 - AppClassLoader(应用程序类加载器) :面向我们用户的加载器,负责加载当前应用classpath下的所有jar包和类。
双亲委派模型
双亲委派模型介绍
每一个类都有一个对应它的类加载器。系统中的 ClassLoder 在协同工作的时候会默认使用 双亲委派模型 。即在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载。加载的时候,首先会把该请求委派该父类加载器的 loadClass() 处理,因此所有的请求最终都应该传送到顶层的启动类加载器 BootstrapClassLoader 中。当父类加载器无法处理时,才由自己来处理。当父类加载器为null时,会使用启动类加载器 BootstrapClassLoader 作为父类加载器。

每个类加载都有一个父类加载器,我们通过下面的程序来验证。
public class ClassLoaderDemo {public static void main(String[] args) {System.out.println("ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader());System.out.println("The Parent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent());System.out.println("The GrandParent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent().getParent());}
}
Output
ClassLodarDemo's ClassLoader is sun.misc.Launcher$AppClassLoader@18b4aac2
The Parent of ClassLodarDemo's ClassLoader is sun.misc.Launcher$ExtClassLoader@1b6d3586
The GrandParent of ClassLodarDemo's ClassLoader is null
AppClassLoader的父类加载器为ExtClassLoader
ExtClassLoader的父类加载器为null,null并不代表ExtClassLoader没有父类加载器,而是 BootstrapClassLoader 。
其实这个双亲翻译的容易让别人误解,我们一般理解的双亲都是父母,这里的双亲更多地表达的是“父母这一辈”的人而已,并不是说真的有一个 Mother ClassLoader 和一个 Father ClassLoader 。另外,类加载器之间的“父子”关系也不是通过继承来体现的,是由“优先级”来决定。官方API文档对这部分的描述如下:
The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a “parent” class loader. When loading a class, a class loader first “delegates” the search for the class to its parent class loader before attempting to find the class itself.
双亲委派模型实现源码分析
双亲委派模型的实现代码非常简单,逻辑非常清晰,都集中在 java.lang.ClassLoader 的 loadClass() 中,相关代码如下所示。
private final ClassLoader parent;
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 首先,检查请求的类是否已经被加载过Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {//父加载器不为空,调用父加载器loadClass()方法处理c = parent.loadClass(name, false);} else {//父加载器为空,使用启动类加载器 BootstrapClassLoader 加载c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {//抛出异常说明父类加载器无法完成加载请求}if (c == null) {long t1 = System.nanoTime();//自己尝试加载c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}
双亲委派模型的好处
双亲委派模型保证了Java程序的稳定运行,可以避免类的重复加载(JVM 区分不同类的方式不仅仅根据类名,相同的类文件被不同的类加载器加载产生的是两个不同的类),也保证了 Java 的核心 API 不被篡改。如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 java.lang.Object 类的话,那么程序运行的时候,系统就会出现多个不同的 Object 类。
如果我们不想用双亲委派模型怎么办?
自定义加载器的话,需要继承 ClassLoader 。如果我们不想打破双亲委派模型,就重写 ClassLoader 类中的 findClass() 方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。但是,如果想打破双亲委派模型则需要重写 loadClass() 方法
自定义类加载器
除了 BootstrapClassLoader 其他类加载器均由 Java 实现且全部继承自java.lang.ClassLoader。如果我们要自定义自己的类加载器,很明显需要继承 ClassLoader。
相关文章:
JVM——类加载器
回顾一下类加载过程 类加载过程:加载->连接->初始化。连接过程又可分为三步:验证->准备->解析。 一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以去完成还可以自定义…...
async/await 编程理解
博客主要是参考 Asynchronous Programming in Rust ,会结合简单的例子,对 async 和 await 做比较系统的理解,如何使用 async 和 await 是本节的重点。 async 和 await 主要用来写异步代码,async 声明的代码块实现了 Future 特性&a…...
1. Java基础知识介绍
文章目录 1. Java基础知识介绍1. 简单输入输出1.1 输入1.2 输出 2. 数据类型2.1 基本数据类型2.2 引用数据类型 3. 函数4. 类基础知识5. 小结 1. Java基础知识介绍 1. 简单输入输出 在Java编程中,我们经常需要与用户进行交互,以获取输入并输出结果。Ja…...
基础shell小技巧01
1. 命令替换 shell脚本中最有用的特性之一是可以从命令输出中提取信息并将其赋给变量。把输出赋给变量之后,就可以随意在脚本中使用了。在脚本中处理数据时,这个特性显得尤为方便。 有两种方法可以将命令输出赋给变量。 反引号(࿰…...
微信小程序--data的赋值与取值的几种方式
通过小程序官方文档可知: 赋值一定需要注意。需要setData的使用,这样页面才刷新,数据才会改变,并且分清that和this的使用 Page() 函数用来注册一个页面。接受一个 object 参数,其指定页面的初始数据、生命周期函数、事…...
条码通讯配置
由Leuze(劳易测) LSIS 222 M5M-R1/MA208i系统组成 连接说明及器件明细: 打开条码调试软件BPS Configuration tool对M208i进行ip 和端口号进行配置,条码选择作为客户端,输入ip和端口号,选择串口通讯波特…...
知网G4期刊《高考》简介及投稿要求
知网G4期刊《高考》简介及投稿要求 一、《高考》期刊简介: 主管单位:长春市委宣传部 主办单位:长春出版社 国内刊号22-1372/G4 国际刊号1673-6265 代号12-240 编辑单位:《高考》杂志社 出版周期:旬刊 类 …...
第7章 CPU前端优化
接下来讨论如何使用CPU监控特性寻找CPU上运行的代码中可被调优的位置。 标准的算法和数据结构在性能敏感型工作负载并不总能表现的很好。例如,在“扁平化”数据结构的冲击下,链表基本上快被放弃了。传统链表中的每个节点都是动态分配的,除了…...
idea新建Java-maven项目时,出现Dependency‘xxx(jar包名)‘ not found的解决方案
项目场景: 项目场景:使用idea创建maven项目时,导入简单依赖时(本文以mysql-connector-java为例)。 问题描述 问题: 首先,在创建新的maven项目中,出现下列两种情况: &am…...
STM32--USART串口
文章目录 通信接口串口通信硬件电路电平标准参数时序 USART主要特性框图 数据帧发送器 波特率发生器SWART串口发送与接收工程串口收发数据包 通信接口 通信接口是指连接中央处理器(CPU)和标准通信子系统之间的接口,用于实现数据和控制信息在不…...
2023年Java毕业设计题目推荐,怎样选题?500道毕业设计题目推荐
大家好,我是程序员徐师兄,最近有很多同学咨询,说毕业设计了,不知道选怎么题目好,有哪些是想需要注意的。 今天,我整理了一些Java毕业设计的题目,可以参考一下,希望对大家有所帮助 文章目录 一、…...
基于数据湖的多流拼接方案-HUDI概念篇
目录 一、为什么需要HUDI? 1. 传统技术选型存在哪些问题? 2. Hudi有什么优点? 基于 Hudi Payload 机制的多流拼接方案: 二、HUDI的应用场景 1. 什么场景适合使用hudi? 2. 什么场景不适合使用hudi? …...
OpenCV基础知识(5)— 几何变换
前言:Hello大家好,我是小哥谈。OpenCV中的几何变换是指改变图像的几何结构,例如大小、角度和形状等,让图像呈现出缩放、翻转、旋转和透视效果。这些几何变换操作都涉及复杂、精密的计算。OpenCV将这些计算过程都封装成了非常灵活的…...
Linux下源码安装MySQL 8.0
MySQL 8.0源码安装 环境准备步骤 环境准备 Linux环境,本文基于CentOS 8 MySQL安装包,本文基于MySQL 8.1,以下为带boost MySQL 8.1源码下载地址: https://dev.mysql.com/get/Downloads/MySQL-8.1/mysql-boost-8.1.0.tar.gz 步骤…...
大聪明教你学Java | 深入浅出聊 Java 内存模型
前言 🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。 🍊支持作者: 点赞👍、关注💖、留言💌~ 在多线程环境下,多个线程同时访问共享数据可能导致一系列问题,如数据不一致、竞态条件和死锁等…...
SAP ABAPG开发屏幕自动生成日期的搜索帮助
代码如下: REPORT z_jason_test_f4 . TABLES: s031. PARAMETER p_spmon TYPE spmon DEFAULT sy-datum0(6) OBLIGATORY. SELECT-OPTIONS s_spmon FOR s031-spmon DEFAULT sy-datum0(6) OBLIGATORY. AT SELECTION-SCREEN ON VALUE-REQUEST…...
leetcode 674. 最长连续递增序列
2023.8.24 与最长递增子序列 类似,不同的是, 本题要求连续序列,所以不需要第二层遍历比较之前所有的元素了,只需要比较上一个元素i-1。 dp[i]的含义为:以nums[i]元素为结尾的序列的最长递增子序列。 注意这里是以i为结…...
Mysql简短又易懂
MySql 连接池:的两个参数 最大连接数:可以同时发起的最大连接数 单次最大数据报文:接受数据报文的最大长度 数据库如何存储数据 存储引擎: InnoDB:通过执行器对内存和磁盘的数据进行写入和读出 优化SQL语句innoDB会把需要写入或者更新的数…...
vue 简单实验 v-model 变量和htm值双向绑定
1.代码 <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <div id"two-way-binding"><p>{{ message }}</p><input v-model"message" /> </div> <script>…...
测试框架pytest教程(8)失败重试-pytest-rerunfailures
pytest-rerunfailures是一个pytest插件,用于重新运行失败的测试用例。当测试用例在第一次运行时失败,该插件会自动重新运行指定次数的失败用例,以提高稳定性和减少偶发性错误的影响。 要使用pytest-rerunfailures插件,需要按照以…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
