JVM深入原理(六)(二):双亲委派机制

目录

6.5. 类加载器-双亲委派机制

6.5.1. 双亲委派机制-作用

6.5.2. 双亲委派机制-工作流程

6.5.3. 双亲委派机制-父加载器

6.5.4. 双亲委派机制-面试题

6.5.5. 双亲委派机制-代码主动加载一个类

6.6. 类加载器-打破双亲委派机制

6.6.1. 打破委派-ClassLoader原理

6.6.2. 打破委派-打破的场景

6.6.3. 打破委派-自定义类加载器

6.6.4. 打破委派-线程上下文类加载器

6.6.5. 打破委派-OSGi模块化

6.7. 类加载器-JDK8前后的类加载器


6.5. 类加载器-双亲委派机制

6.5.1. 双亲委派机制-作用

  • 双亲委派机制的作用:解决谁来加载类的问题
    1. 保证类加载的安全性:避免恶意代码替换JDK中的核心类库(比如:java.lang.String),确保核心类库的完整性和安全性
    2. 避免类的重复加载:避免一个类被反复加载

6.5.2. 双亲委派机制-工作流程

  • 双亲委派机制的工作流程:当类加载器接收到加载类的任务时,会自底向上查找父类加载器是否加载过该类,是则结束这个过程,否则自顶向下进行加载该类

    • 自底向上工作流程:每个类加载器都有父类加载器,在类加载过程中,每个类加载器会检查自身是否加载了该类,是则直接返回该类,否则将加载请求委派给父类加载器
    • 自底向上工作优点:只要一个类加载器加载过该类就会直接返回,避免了重复加载
    • 自顶向下工作流程:父类加载器会检查当前类是否在自己的加载目录中,是则加载后返回类对象,否则交给子类去加载
    • 自顶向下的优点:实现从上到下的加载优先级

6.5.3. 双亲委派机制-父加载器

  • 父加载器辨析:每个Java实现的类加载器中保存了一个成员变量叫"父"(parent)类加载器,可以理解为它的上级,但不是继承关系

    • 应用程序类加载器的父类加载器:扩展类加载器
    • 扩展类加载器的父类加载器:null,启动类加载器是JVM源码中的,Java代码是获取不到的,但是代码逻辑上启动类加载器的父类加载器还是启动类加载器
    • 启动类加载器的父类加载器:启动类加载器是用C++编写的没有父类加载器

6.5.4. 双亲委派机制-面试题

  • 启动类加载器加载,根据双亲委派机制,它的优先级是最高的
  • 不能,因为启动类加载器在程序启动时已经加载了JDK提供的String类,接收到委派请求时会直接返回加载好的String类

6.5.5. 双亲委派机制-代码主动加载一个类

  • 使用Java代码可以主动加载一个类,有两种实现方式:
    1. 调用Class.forName方法使当前类的类加载器去加载该类
    2. 调用getClassLoader方法获取当前类的类加载器,再用类加载器的loadClass方法让该类加载器加载指定的方法

6.6. 类加载器-打破双亲委派机制

6.6.1. 打破委派-ClassLoader原理

  • ClassLoader的原理就存在于四个核心方法中

  1. loadClass:
    • 作用:类加载的入口,内部实现双亲委派机制,内部会调用findClass
    • 代码逻辑:
    1. 使用synchronized加锁,防止多线程情况下出现类被多次加载
    2. 使用findLoadClass方法判断这个类是否被当前类加载器加载过

      1. 未被加载过,则判断父类加载器是否为空
        1. 不为空,则由父类加载器再判断是否加载过这个类,依次类推
        2. 为空,则由启动类加载器去加载
      1. 已被加载过,则直接返回这个类
    1. 执行完向上委派动作,但类任未被加载,则由当前类加载器加载
      1. 使用URLClassLoader的findClass方法获取特定目录下的Class字节码文件,获取文件对象
    1. 调用重载方法传入resolve=false,不执行连接的过程
  1. findClass:由类加载器子类实现,获取二进制数据时调用defineClass,比如URLClassLoader会根据文件路径去获取类文件的二进制数据
  2. defineClass:对类名进行校验,调用JVM方法将字节码信息加载到JVM运行时数据区
  3. resolveClass:执行类生命周期中的连接阶段

6.6.2. 打破委派-打破的场景

  • Tomcat打破双亲委派机制的原因:Tomcat程序中运行多个Web应用时,如果Web应用中出现相同限定名的类,Tomcat要保证这些类能够正常加载并运行且保证他们是不同的类,Tomcat就需要打破双亲委派机制

  • Tomcat打破双亲委派机制的方式:Tomcat为每一个Web应用提供了自定义类加载器来加载对应的类,这样就实现了应用之间的类的隔离

6.6.3. 打破委派-自定义类加载器

  • 自定义类加载器打破双亲委派机制的方法:复写ClassLoader中的loadClass方法
  • 常见问题:
    • 要加载的类名如果是以java.开头,则会抛出安全性异常
    • 加载自定义的类都会有一个共同

      的父类Object,需要在代码中交由父类加载器去加载

    • 自定义类加载器不手动指定parent会默认指定应用类加载
    • 两个自定义类加载器加载同一个类会被认为是两个对象,只有相同的类加载器+想通的类限定名才会被认为是一个对象

6.6.4. 打破委派-线程上下文类加载器

  • 线程上下文类加载器应用场景:JDBC(为例),JNDI
  • JDBC概述:JDBC提供DriverManager来管理jar包中引入的数据库驱动,这样就能在Java中操作不同的数据库
  • JDBC打破委派困境:DriverManager位于rt.jar包中,由启动类加载器加载,但依赖中的MySQL驱动实现类需要应用类加载器去加载

  • JDBC-SPI机制:SPI(Service Provider Interface)JDK内置服务发现机制,通过SPI快速找到Driver接口的实现类,类似Spring中的依赖注入
  • JDBC工作原理:MySQL为例

    1. 启动类加载器加载位于rt.jar包的DriverManager
    2. 初始化DriverManager时,通过SPI机制加载jar包中的数据库驱动实现类,将此实现类注册到DriverManager中交由他管理
      • DriverManager利用SPI机制会去加载META-INF/services路径下的java.sql.Driver文件,将MySQL实现了Driver接口的驱动实现类的全限定名写入文件就可以被加载并管理
    1. SPI中利用了线程上下文类加载器(一般是应用类加载器)去加载获取的Driver驱动类并创建对象

      • DriverManager使用ServiceLoader去加载Driver实现类,ServiceLoader中获取线程上下文类加载器去加载实现类
    1. 这种由启动类加载器加载的类去委派应用程序类加载器去加载类的方式打破了双亲委派机制
    2. 但是JDBC案例中都使用的是JDK提供的类加载器还是会走双亲委派流程,并没有重写loadClass,也可以说没有打破双亲委派机制

6.6.5. 打破委派-OSGi模块化

  • OSGi作用:OSGi是模块化框架,解决早起JDK所有核心类都放在rt.包下难以管理的问题,它实现同级之间的类加载器委托加载.还使用类加载器实现了热部署功能

6.7. 类加载器-JDK8前后的类加载器

  • JDK8之前版本:扩展类加载器和应用程序类加载器的源码都位于rt.jar包下的sun.misc.Launcher.java中,这两个加载器都实现了URLClassLoader,也可以说JDK8之前类加载器是按照类的位置去加载的

  • JDK8之后版本:JDK9引入了module概念,类不在放在jar包中加载,而是放在一个个jmod文件中,从jmod文件中加载文件,类加载器发生很多变化:

    1. 启动类加载器由Java编写,位于jdk.internal.loader.ClassLoader类中

      1. Java中的BootClassLoader继承自BuiltinClassLoader实现从模块中找到要加载的字节码文件
      2. 启动类加载器依然无法通过Java代码找到保持了统一
    1. 扩展类加载器被替换成了平台类加载器(Platform Class Loader)

      1. 平台类加载器遵循模块化方式加载字节码文件,继承关系从URLClassLoader变为BuiltinClassLoader,BuiltinClassLoader实现了从模块中加载字节码文件,平台类加载器的存在更多是为老板的设计方案兼容,自己没有特殊逻辑

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

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

相关文章

Linux 文件系统超详解

一.磁盘 磁盘是计算机的主要存储介质,它可以存储大量二进制数据,即使断电后也可以保证数据不会丢失。下面我们将了解磁盘的物理结构、存储结构以及逻辑结构。 磁盘的存储结构 1. 磁盘寻址的时候,基本单位既不是bit也不是byte,而…

2025年大模型与Transformer架构:重塑AI未来的科技革命

引言:一场关于智能的革命 想象一下,当你向一个虚拟助手提问时,它不仅能够准确理解你的需求,还能生成一段流畅且富有逻辑的回答;或者当你上传一张模糊的照片时,系统可以快速修复并生成高清版本——这一切的…

GO语言学习(16)Gin后端框架

目录 ☀️前言 1.什么是前端?什么是后端?🌀 2.Gin框架介绍 🌷 3.Gin框架的基本使用 -Hello,World例子🌷 🌿入门示例 - Hello,World 💻补充(一些常用的网…

深入解析 Git Submodule:从基础到高级操作指南

深入解析 Git Submodule:从基础到高级操作指南 一、Git Submodule 是什么? git submodule 是 Git 提供的一个强大功能,允许在一个 Git 仓库(主仓库)中嵌入另一个独立的 Git 仓库(子模块)。主仓…

电子电气架构 --- EEA演进与芯片架构转移

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…

如何用deepseek生成流程图

软件准备: 在线流程图【Flowchart Maker & Online Diagram Software】或【process on】 步骤: 1、用 【DeepSeek】生成 结构化内容(Mermaid文件) 1.1、向deepseek输入指令:【帮我用mermaind写出“某某”的具体…

【华为OD技术面试真题 - 技术面】- Java面试题(17)

华为OD面试真题精选 专栏:华为OD面试真题精选 目录: 2024华为OD面试手撕代码真题目录以及八股文真题目录 文章目录 华为OD面试真题精选虚拟机分区1. **虚拟磁盘分区**2. **虚拟机的内存分区**3. **CPU分配**4. **虚拟网络分区**5. **存储虚拟化和分区**6. **虚拟机分区管理**…

Linux | I.MX6ULL内核及文件系统源码结构(7)

01 类型 描述 备注 ARM 交叉编译器 版本:4.9.4 提供软件工具 Uboot 版本:2016.03 提供源码 支持LCD显示;支持网口; 支持 EMMC,NAND FLASH; 支持环境变量修改保存 Linux 内核 版本:4.1.15 提供…

0基础入门scrapy 框架,获取豆瓣top250存入mysql

一、基础教程 创建项目命令 scrapy startproject mySpider --项目名称 创建爬虫文件 scrapy genspider itcast "itcast.cn" --自动生成 itcast.py 文件 爬虫名称 爬虫网址 运行爬虫 scrapy crawl baidu(爬虫名) 使用终端运行太麻烦了,而且…

鸿蒙NEXT小游戏开发:猜小球

1. 引言 “猜小球”是一个经典的益智游戏,通常由一名表演者和多名参与者共同完成。表演者会将一个小球放在一个杯子下面,然后将三个杯子快速地交换位置,参与者则需要猜出最终哪个杯子下面有小球。本文将介绍如何使用HarmonyOS NEXT技术&…

网络购物谨慎使用手机免密支付功能

在数字经济蓬勃发展的当下,“免密支付”成为许多人消费时的首选支付方式。 “免密支付”的存在有其合理性。在快节奏的现代生活中,时间愈发珍贵,每节省一秒都可能带来更高的效率。以日常通勤为例,上班族乘坐交通工具时&#xff0c…

记录 | Android getWindow().getDecorView().setSystemUiVisibility(...)设置状态栏属性

纯纯的一边开发一边学习,是小白是菜鸟,单纯的记录和学习,大神勿喷,理解有错望指正~ getWindow().getDecorView().setSystemUiVisibility(…) 该方法用于控制系统 UI(如状态栏、导航栏)的可见性…

java虚拟机---JVM

JVM JVM,也就是 Java 虚拟机,它最主要的作用就是对编译后的 Java 字节码文件逐行解释,翻译成机器码指令,并交给对应的操作系统去执行。 JVM 的其他特性有: JVM 可以自动管理内存,通过垃圾回收器回收不再…

VectorBT:使用PyTorch+LSTM训练和回测股票模型 进阶四

VectorBT:使用PyTorchLSTM训练和回测股票模型 进阶四 本方案融合 LSTM 时序预测与动态风险控制。系统采用混合架构,离线训练构建多尺度特征工程和双均线策略,结合在线增量更新持续优化模型。技术要点包括三层特征筛选、波动率动态仓位管理、混…

前端中rem,vh,vw

1. rem&#xff08;Root EM&#xff09; 参照对象 基准&#xff1a;相对于 根元素&#xff08;<html>&#xff09;的 font-size 计算。 默认情况下&#xff0c;浏览器的根 font-size 为 16px&#xff08;即 1rem 16px&#xff09;&#xff0c;但可通过 CSS 修改&#…

详解 MySQL 常见的存储引擎及它们之间的区别

MySQL 支持多种存储引擎&#xff0c;每种引擎针对不同的应用场景提供了特定的特性和优化。下面是几种常见的存储引擎以及它们之间的主要区别&#xff1a; 常见存储引擎 1. InnoDB&#xff08;重点&#xff09; 事务支持&#xff1a; 完全支持 ACID 事务&#xff0c;确保数据一…

html+css+js 实现一个贪吃蛇小游戏

目录 游戏简介 游戏功能与特点 如何玩转贪吃蛇 游戏设计与实现 HTML结构 JavaScript核心实现 代码结构&#xff1a; 效果 关于“其他游戏” 游戏简介 贪吃蛇是一款经典的单人小游戏&#xff0c;玩家通过控制蛇的移动&#xff0c;吃掉食物来增加长度&#xff0c;避免撞…

GLSL(OpenGL 着色器语言)基础语法

GLSL&#xff08;OpenGL 着色器语言&#xff09;基础语法 GLSL&#xff08;OpenGL Shading Language&#xff09;是 OpenGL 计算着色器的语言&#xff0c;语法类似于 C 语言&#xff0c;但提供了针对 GPU 的特殊功能&#xff0c;如向量运算和矩阵运算。 着色器的开头总是要声明…

ngx_http_core_merge_srv_conf

定义在 src\http\ngx_http_core_module.c static char * ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) {ngx_http_core_srv_conf_t *prev parent;ngx_http_core_srv_conf_t *conf child;ngx_str_t name;ngx_http_server_name_t…

uni-app:firstUI框架的选择器Select改造,添加一个搜索的插槽

<fui-select :show"showSiteType" :options"siteTypeList" textKey"dict_label" title"请选择站点类型" confirm"chooseSiteType" close"onCloseSiteType"><template v-slot:search><view><…