深入理解Java类加载机制中的双亲委派模型--根据源码探讨

news2024/11/17 3:30:36

前言:
今天和大家探讨一道Java中经典的面试题,这道面试题经常出现在各个公司的面试中,本篇文章主要讲解ava类加载机制中的双亲委派模型的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。

如果文章有什么需要改进的地方欢迎大佬提出,对大佬有帮助希望可以支持下哦~

小威在此先感谢各位小伙伴儿了😁

在这里插入图片描述

以下正文开始

文章目录

  • Java中的类加载器
    • 启动类加载器(Bootstrap ClassLoader)
    • 扩展类加载器(Extension ClassLoader)
    • 应用程序类加载器(Application ClassLoader)
    • 自定义类加载器(Custom ClassLoader)
  • 双亲委派模型
  • 双亲委派模型源码
  • 如何打破双亲委派模型

Java中的类加载器

在介绍双亲委派模型之前,首先先介绍下Java中的类加载器。
在这里插入图片描述

启动类加载器(Bootstrap ClassLoader)

首先先介绍下类加载器中的重量级器物,就是大名鼎鼎–启动类加载器。

为什么说他是重量级的恩,因为它是Java类加载器层次结构的最顶层,由虚拟机实现,用于加载Java核心类库,如java.lang和java.util等。

既然是最顶层的类加载器,我们就康康它有什么作用:

启动类加载器是由C/C++编写的,无法直接在Java代码中获取其引用。 它负责加载Java运行时环境所需的基本类。

扩展类加载器(Extension ClassLoader)

接着我们看一下Java加载器中的第二号人物–扩展类加载器。

扩展类加载器是由Java编写的,它是启动类加载器的子类。 它负责加载Java扩展类库,位于jre/lib/ext路径下的JAR文件。
扩展类加载器可以通过java.ext.dirs系统属性来指定其他目录作为扩展类库的路径。

应用程序类加载器(Application ClassLoader)

接着介绍最底层的加载器–应用程序类加载器。

应用程序类加载器是Java类加载器层次结构的最底层,也称为系统类加载器。
它负责加载应用程序类路径(Classpath)下的类,包括开发者自己编写的类和第三方库。
应用程序类加载器可以通过-classpath或-cp选项来指定加载类的路径。

自定义类加载器(Custom ClassLoader)

除了上述系统类的加载器,我们开发者还可以自定义加载器-惊不惊喜,意不意外。

在这里插入图片描述

自定义类加载器是开发者根据需求编写的自定义加载器,继承自ClassLoader类
它可以根据特定的加载规则和需求,从不同的来源加载类,比如本地文件系统、网络等。
自定义类加载器需要实现findClass()方法,指定类的加载规则,然后通过defineClass()方法加载类的字节码。

双亲委派模型

看到这里,上我们的重头菜,这块知识是面试中的重点内容。

在这里插入图片描述

双亲委派(Parent Delegation)是Java类加载机制中一种重要的实现方式,它通过一种递归的方式在类加载器之间建立了父子关系,并且定义了类加载的优先级。该模型主要用于解决类加载的冲突和隔离问题,保证Java应用程序的稳定性和安全性。

在Java类加载机制中,每个类加载器都有一个父加载器。当一个类加载器需要加载一个类时,它首先会委托给它的父加载器进行加载。只有当父加载器无法加载时,子加载器才会尝试加载。这种递归的委派模型可以形成一个类加载器的层次结构,称为类加载器树。

我看了《深入理解Java虚拟机-第三版》中的讲解,挺详细的,这里分享给大家:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父类加载器反馈自己无法加载这个请求时,子加载器才会尝试自己去加载。
在这里插入图片描述

双亲委派模型源码

首先可以先尝试自己看下源码,非常通俗易懂:

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) {
            // 如果父类加载器也无法找到类,则尝试自己加载
            c = findClass(name);
        }
    }
    
    if (resolve) {
        resolveClass(c);
    }
    
    return c;
}

在上面的源码中,我们可以看到双亲委派机制的体现。当loadClass方法被调用时,首先会检查该类是否已经被加载。如果没有加载,那么会按照以下步骤进行处理:

  1. 首先,调用findLoadedClass(name)方法检查类是否已经被其他类加载器加载过。如果是,则直接返回该类的Class对象。

  2. 如果这个类还未加载,则尝试委派给父类加载器加载。通过parent.loadClass(name, false)方法,将类加载任务传递给父类加载器。这个过程中,父类加载器会重复执行上述流程,直到达到引导类加载器为止。

  3. 如果所有的父类加载器都无法加载该类,那么会尝试使用启动类加载器加载。这是Java类加载器层次结构的最顶层。

  4. 如果引导类加载器仍然无法找到所需的类,就会调用findClass(name)方法在当前类加载器的作用域内查找并加载该类。

  5. 到最后,如果resolve参数为true,就会调用resolveClass©方法进一步解析和链接该类。

在这里插入图片描述

如何打破双亲委派模型

其实双亲委派模型并不是具有强制性约束的模型,虽然它有助于保证类的隔离和加载的顺序,但有时候我们可能需要打破这种机制,比如我们在特殊情况下需要自定义类加载逻辑或实现热部署的时候。

上周面试问道了这个问题,所以在这里也介绍几种打破Java中双亲委派机制的方法:

  1. 自定义类加载器:我们自定义一个继承自ClassLoader的类加载器,重写loadClass方法,可以实现自己的类加载逻辑。在我们定义的这个方法中,可以在需要时跳过父类加载器并直接加载类,从而打破双亲委派机制。但是,在自定义类加载器中打破双亲委派机制可能会导致类的隔离性和安全性问题,所以我们在使用时要慎重。

  2. 线程上下文类加载器:Java中提供了线程上下文类加载器(Thread Context ClassLoader)的概念,它可以在某些情况下打破双亲委派机制。例如,在JNDI、SPI(Service Provider Interface)和一些框架中,线程上下文类加载器可以用来加载指定的类,从而不受双亲委派机制的限制。

  3. 通过反射机制:使用反射机制可以直接调用Class类的defineClass方法,这样可以绕过双亲委派机制直接加载指定的类。但是,在使用这种方式时,我们需要自行处理类加载的顺序和依赖关系,因为双亲委派机制不再起作用。

综上所述,不正确地使用或滥用这些方法可能导致类加载冲突、安全问题以及代码的不稳定性 ,因此我们还需要在明确的需求和充分的理解下使用(面试会背诵就行【手动狗头】)。

在这里插入图片描述
文章到这里就先结束了,感兴趣的可以订阅专栏哈,后续会继续分享相关的知识点。

在这里插入图片描述

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

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

相关文章

Cesium态势标绘专题-三角旗标、矩形旗标、曲线旗标(标绘+编辑)

标绘专题介绍:态势标绘专题介绍_总要学点什么的博客-CSDN博客 入口文件:Cesium态势标绘专题-入口_总要学点什么的博客-CSDN博客 辅助文件:Cesium态势标绘专题-辅助文件_总要学点什么的博客-CSDN博客 本专题没有废话,只有代码,代码中涉及到的引入文件方法,从上面三个链…

前端JavaScript作用域详解

目录 前言 什么是作用域 作用域类型 全局作用域 局部作用域 块级作用域 ES6之前 ES6以后 作用域链 变量提升 基础概念 优先级问题 闭包 定义 特点 使用场景 封装私有变量 延长变量周期 模块化、命名空间 缓存 ES6的作用域 const、let 块级作用域 变量提…

tinymce4/5实现将word中内容(文字图片等)直接粘贴至编辑器中——利用插件tinymce-powerpaste-plugin

TinyMCE是一款易用、且功能强大的所见即所得的富文本编辑器。同类程序有&#xff1a;UEditor、Kindeditor、Simditor、CKEditor、wangEditor、Suneditor、froala等等。 TinyMCE的优势&#xff1a; 开源可商用&#xff0c;基于LGPL2.1 插件丰富&#xff0c;自带插件基本涵盖日常…

关于时序图

时序图 01 什么是时序图&#xff1f;02 时序图的组成元素2.1 对象2.2 生命线2.3 消息 03 如何绘制 01 什么是时序图&#xff1f; 时序图是UML交互图中的一类&#xff0c;又名序列图、顺序图。 用于描述对象之间的传递消息的时间顺序&#xff08;包括发送消息、接收消息、处理…

一个女程序员的成长之路

2013年大学毕业了&#xff0c;带着迷茫与好玩&#xff0c;我还年轻的心态&#xff0c;开始在郑州寻觅工作机会&#xff0c;最后很荣幸的在一家小公司入职了&#xff0c;工作的内容是给种植大棚的用户打电话&#xff0c;推销农药。每天就是在网上各种农业平台上面找号码&#xf…

ASIC-WORLD Verilog(11)过程时序控制

写在前面 在自己准备写一些简单的verilog教程之前&#xff0c;参考了许多资料----Asic-World网站的这套verilog教程即是其一。这套教程写得极好&#xff0c;奈何没有中文&#xff0c;在下只好斗胆翻译过来&#xff08;加了自己的理解&#xff09;分享给大家。 这是网站原文&…

【vue】vue中Mixins的用法(jeecg-boot为例):

文章目录 一、jeecg-boot本身只有JeecgListMixin.js二、使用Mixin:三、mixins详解&#xff1a;【1】由于每个项目的接口和参数不同>这里引进js进行处理&#xff0c;不在Mixin里面处理了&#xff08;Mixin只做公共数据处理&#xff09;【2】公共的页面字典【3】解决方法里面不…

2009年上半年 软件设计师 上午试卷3

●下图属于UML 中的&#xff08;46),其中&#xff0c;AccountManagement 需要&#xff08;47)。 (46)A.组件图 B.部署图 C.类图 D.对象图 (47)A.实现 IdentityVerifier 接口并被 CreditCardServices 调用 B.调用 CreditCardServices 实现的 Identity Verifier 接口 C.实现 I…

设计模式大白话——装饰者模式

装饰者模式 文章目录 装饰者模式一、概述二、应用场景三、代码示例四、小结 一、概述 ​ 装饰者模式&#xff0c;此模式最核心之处在于装饰二字&#xff0c;之所以需要装饰&#xff0c;是因为基础的功能无法满足需求&#xff0c;并且装饰是临时的&#xff0c;并不是永久的&…

基于Java+spring+springMvc+mybatis+jsp学生选课管理系统

基于JavaspringspringMvcmybatisjsp学生选课管理系统 一、系统介绍二、功能展示1.课程列表(学生)2.已选课程(学生)3.已修课程(学生)4.我的课程&#xff08;老师&#xff09;5.课程打分&#xff08;老师&#xff09;6.课程管理、学生管理、教师管理&#xff08;系统管理员&#…

python字典:怎么取出key对应的值

目录 python中的字典是什么 怎么判断key是否在字典中 怎么取出key对应的值 总结 python中的字典是什么 在Python中&#xff0c;字典&#xff08;Dictionary&#xff09;是一种无序且可变的数据类型&#xff0c;用于存储键-值&#xff08;Key-Value&#xff09;对。字典通过…

电脑卡顿反应慢怎么处理?提升反应速度的方法

电脑卡顿反应慢是很常见的问题&#xff0c;然而&#xff0c;我们可以采取一些方法来处理这个问题&#xff0c;帮助大家提升电脑反应速度。​ 一、提升电脑反应速度的方法 当电脑运行顺畅时&#xff0c;我们的工作体验也会更加愉悦。然而&#xff0c;如果电脑出现卡顿反应慢的…

【项目设计】MySQL 连接池的设计

目录 &#x1f449;关键技术点&#x1f448;&#x1f449;项目背景&#x1f448;&#x1f449;连接池功能点介绍&#x1f448;&#x1f449;MySQL Server 参数介绍&#x1f448;&#x1f449;功能实现设计&#x1f448;&#x1f449;开发平台选型&#x1f448;&#x1f449;MyS…

【雕爷学编程】MicroPython动手做(24)——掌控板之拓展掌控宝

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

【雕爷学编程】MicroPython动手做(23)——掌控板之WiFi与蓝牙2

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

1400*D. Candy Box (easy version)(贪心)

3 10 9 Example input 3 8 1 4 8 4 5 6 3 8 16 2 1 3 3 4 3 4 4 1 3 2 2 2 4 1 1 9 2 2 4 4 4 7 7 7 7 output 题意&#xff1a; n个糖果&#xff0c;分为多个种类&#xff0c;要求尽可能的多选&#xff0c;并且使得不同种类的数量不能相同。 解析&#xff1a; 记录每种糖…

音视频技术开发周刊 | 304

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 更强的Llama 2开源&#xff0c;可直接商用&#xff1a;一夜之间&#xff0c;大模型格局变了 Meta 终于发布了大家期待已久的免费可商用版本 Llama 2。 6000份问卷透露出AI…

Java生成二维码——附Utils工具类

参加2023年的计算机设计大赛国赛&#xff0c;拿到了一等奖。 现在将项目中的工具类代码剥离出来&#xff0c;方便之后项目开发中复用。 实现效果&#xff1a; 代码实现&#xff1a; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import c…

挑战双面侧柱碰试验:比亚迪CTB保障高品质出行

对于用户来说&#xff0c;选择汽车时最应该重视的要素是什么&#xff1f; 第一&#xff0c;是安全&#xff1b;第二&#xff0c;是安全&#xff1b;第三&#xff0c;还是安全&#xff01; 那么作为新能源汽车的代表&#xff0c;比亚迪在保障驾乘人员的安全方面又是怎样做的呢&a…

基于SpringCloud+Vue的分布式架构网上商城系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…