阿里二面:双亲委派机制?原理?能打破吗?

news2024/11/26 15:52:06

最近收到粉丝私信,大厂面试常问:“什么是双亲委派机制?类加载过程怎样?优缺点是什么?原理是何?能打破双亲委派机制吗?如何打破?有哪些场景使用?

故借此简单总结一下,更多可以点击 【面试笔记】 覆盖全面考题!!

话不多说,开搞。

什么是双亲委派机制?

1、理解概述

双亲委派机制(Parent Delegation Model)是Java虚拟机(JVM)中的一种类加载机制。它是一种层次化的类加载器结构,通过委派给父类加载器来加载类,以保证类的唯一性和安全性。

在Java中,每个类都需要在运行时被加载到内存中才能被使用。类加载器负责将类的字节码加载到内存中,并生成对应的Class对象。双亲委派机制是一种类加载器的工作方式,它通过一种层次化的结构来加载类,保证类的加载是有序、唯一且安全的

2、类加载过程

类加载过程是将类的字节码加载到内存中,并生成对应的Class对象的过程。类加载过程主要包括以下几个步骤:

  1. 加载(Loading):类加载的第一个阶段是加载,即将类的字节码文件加载到内存中。加载阶段由类加载器完成,类加载器根据类的全限定名(包括包名和类名)来定位并读取字节码文件。加载阶段的结果是在内存中生成一个代表该类的Class对象。
  2. 验证(Verification):在验证阶段,对加载的字节码进行验证,确保字节码的正确性和安全性。验证阶段包括以下几个方面的验证:文件格式验证、元数据验证、字节码验证和符号引用验证。
  3. 准备(Preparation):在准备阶段,为类的静态变量分配内存并设置默认初始值。这些变量包括静态变量和静态常量。
  4. 解析(Resolution):在解析阶段,将符号引用解析为直接引用。符号引用是一种符号名称,可以是类、字段、方法等的引用。直接引用是直接指向内存中的地址,可以是指向方法区中的方法、字段等的指针。
  5. 初始化(Initialization):在初始化阶段,对类进行初始化,包括执行静态变量的赋值和静态代码块的执行。初始化阶段是类加载过程的最后一个阶段,只有在初始化阶段完成后,类才能被正常使用。

需要注意的是,类加载过程是按需加载的,即在首次使用类时才会进行加载。而且类加载过程是线程安全的,即同一个类在多线程环境下只会被加载一次。

另外,类加载过程可以由自定义的类加载器来扩展或修改,默认的类加载器是应用程序类加载器(Application ClassLoader),它负责加载应用程序的类。自定义类加载器可以实现一些特定的需求,如加载加密的字节码文件、从网络或其他非标准位置加载类等。

反映在双亲委派机制上:

image-20231029131917973

具体来说,当一个类加载器收到加载类的请求时,它会先检查自己是否已经加载过这个类。如果已经加载过,则直接返回已加载的类。如果没有加载过,则将加载请求委派给它的父类加载器。父类加载器会按照同样的方式继续检查是否已经加载过这个类,直到达到顶层的启动类加载器。如果所有的父类加载器都无法加载这个类,则由当前类加载器自己去加载。如果加载成功,则将生成的Class对象返回给请求者。

3、类加载器的层次结构

类加载器的层次结构是指类加载器之间的父子关系,它们按照一定的顺序组成了一个层次化的结构。在Java中,双亲委派机制的类加载器结构一般包括三个层次:

  1. 启动类加载器(Bootstrap ClassLoader):也称为根类加载器,它是虚拟机的一部分,通常由本地代码实现,不是Java类。它负责加载Java的核心类库,如java.lang包中的类。启动类加载器是所有其他类加载器的父加载器,它没有父加载器。
  2. 扩展类加载器(Extension ClassLoader):它是由Java编写的类,是由启动类加载器加载的。扩展类加载器负责加载Java的扩展类库,如javax包中的类。它的父加载器是启动类加载器。
  3. 应用程序类加载器(Application ClassLoader):也称为系统类加载器,它负责加载应用程序的类,即开发者自己编写的类。应用程序类加载器是由扩展类加载器加载的。它的父加载器是扩展类加载器。

除了这三个主要的类加载器,还有一些其他的类加载器,如自定义的类加载器。自定义的类加载器可以继承自应用程序类加载器或其他类加载器,形成更复杂的层次结构。

类加载器的层次结构是通过双亲委派机制来实现的。当一个类加载器收到加载类的请求时,它会先向上委派给父类加载器,由父类加载器尝试加载。

父类加载器会按照同样的方式继续向上委派,直到达到顶层的启动类加载器。如果所有的父类加载器都无法加载这个类,则由当前类加载器自己去加载。

这样的层次结构保证了类加载的一致性和安全性,避免了类的重复加载和恶意代码的替换。

双亲委派机制的作用是什么?

双亲委派机制的作用是保证Java类的加载的一致性和安全性;具体来说,双亲委派机制的作用有以下几个方面:

  1. 避免重复加载:当一个类加载器收到加载类的请求时,它会先向上委派给父类加载器,由父类加载器尝试加载。父类加载器会按照同样的方式继续向上委派,直到达到顶层的启动类加载器。如果所有的父类加载器都无法加载这个类,则由当前类加载器自己去加载。这样的层次结构保证了类的加载只会发生一次,避免了重复加载。
  2. 类的隔离性:每个类加载器都有自己的命名空间,它只能加载自己命名空间下的类。当一个类加载器尝试加载一个类时,它会先检查自己的命名空间中是否已经加载了这个类。如果已经加载,则直接返回已加载的类;如果没有加载,则委派给父类加载器加载。这样的隔离性保证了不同类加载器加载的类之间互不影响,避免了类的冲突和版本不一致的问题。
  3. 安全性:通过双亲委派机制,Java类的加载可以由更高层次的类加载器来完成,这些类加载器通常是由Java官方或其他可信任的实体提供的。这样可以确保核心类库和扩展类库的安全性,避免了恶意代码的替换和执行。

总的来说,双亲委派机制通过层次化的类加载器结构,保证了Java类的加载的一致性和安全性,避免了重复加载和类的冲突,同时也提供了一种安全的加载机制,防止恶意代码的执行。

然而,双亲委派机制也有一些缺点:

  1. 限制了类加载的灵活性:双亲委派机制要求类加载器按照一定的顺序去加载类,这限制了类加载的灵活性。有时候,我们可能需要自定义的类加载器来加载特定的类,但由于双亲委派机制的存在,这些类可能会被父类加载器加载,无法实现自定义加载的需求。
  2. 难以实现类的动态更新:由于双亲委派机制的存在,当一个类被加载后,它的类定义就不能再被修改。这意味着如果我们想要在运行时动态更新一个类的定义,就需要重新加载整个类及其依赖的类。这对于一些需要频繁更新的应用场景来说,可能会带来一些困扰。

总的来说,双亲委派机制在保证类加载的一致性和安全性方面具有明显的优势,但也存在一定的限制和缺点。在实际应用中,需要根据具体的需求来权衡使用双亲委派机制的利与弊。

双亲委派机制的工作原理是什么?

双亲委派机制的工作原理可以简单概括为以下几个步骤:

  1. 当一个类加载器收到加载类的请求时,它会先检查自己的命名空间中是否已经加载了这个类。如果已经加载,则直接返回已加载的类;如果没有加载,则继续下一步。
  2. 类加载器会将加载请求委派给父类加载器。父类加载器会按照同样的方式继续向上委派,直到达到顶层的启动类加载器。
  3. 如果所有的父类加载器都无法加载这个类,则由当前类加载器自己去加载。当前类加载器会根据自己的加载策略,从指定的路径或资源中加载类的字节码,并将其转换为可执行的类。
  4. 加载完成后,将加载的类及其相关信息存放在当前类加载器的命名空间中,以便后续的类加载请求可以直接使用。

通过这样的层次结构和委派机制,双亲委派机制保证了类的加载只会发生一次,避免了重复加载;同时,也保证了类的隔离性,不同类加载器加载的类之间互不影响;还能提供一种安全的加载机制,防止恶意代码的执行

需要注意的是,双亲委派机制并不是强制性的,可以根据具体的需求进行调整或扩展。在Java中,可以通过自定义类加载器来改变类加载的行为,实现一些特定的需求。

这样可以使得:

- 避免类的重复加载:通过委派给父类加载器,可以避免同一个类被多个类加载器加载,节省了内存空间。

- 提高类加载的效率:父类加载器已经加载过的类可以直接返回,无需再次加载,提高了类加载的效率。

- 提高Java程序的安全性:防止恶意代码替换核心类库,提高了Java程序的安全性。

然而,有时候我们需要打破双亲委派机制,自定义类加载器来实现特定的需求。这需要谨慎操作,因为打破双亲委派机制可能导致类加载的混乱和安全性问题。

打破双亲委派机制?

为什么要打破双亲委派机制吗?

打破双亲委派机制的主要原因是为了满足一些特定的需求和场景,例如:

  1. 实现类的热部署:在某些应用场景下,需要在运行时动态加载和替换类,以实现热部署的功能。而双亲委派机制会导致类的加载只发生一次,无法实现类的热替换。通过打破双亲委派机制,可以自定义类加载器,在需要时重新加载和替换类。
  2. 加载非标准的类文件:有些特殊的类文件,如动态生成的字节码、非标准的类文件格式等,无法通过标准的类加载器加载。通过打破双亲委派机制,可以自定义类加载器,实现对这些非标准类文件的加载和解析。
  3. 实现类加载的动态控制:有些应用需要对类的加载进行特殊的控制,例如对特定的类进行加密、解密或验证等操作。通过打破双亲委派机制,可以自定义类加载器,在加载类时进行特殊的处理。

需要注意的是,打破双亲委派机制可能会引入一些潜在的风险和问题,如类的冲突、不一致性等。因此,在打破双亲委派机制时,需要谨慎考虑,并确保自定义的类加载器能够正确处理类的加载和依赖关系。

怎样打破双亲委派机制?

在Java中,有以下几种方法可以打破双亲委派机制:

  1. 自定义类加载器:通过自定义ClassLoader的子类,重写findClass()方法,实现自定义的类加载逻辑。在自定义类加载器中,可以选择不委派给父类加载器,而是自己去加载类。
public class CustomClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 自定义类加载逻辑,例如从特定路径加载类文件
        byte[] classBytes = loadClassBytes(name);
        return defineClass(name, classBytes, 0, classBytes.length);
    }

    private byte[] loadClassBytes(String name) {
        // 从特定路径加载类文件,并返回字节码
        // ...
    }
}
  1. 线程上下文类加载器:通过Thread类的setContextClassLoader()方法,可以设置线程的上下文类加载器。在某些框架或库中,会使用线程上下文类加载器来加载特定的类,从而打破双亲委派机制。
  2. OSGi框架:OSGi(Open Service Gateway Initiative)是一种动态模块化的Java平台,它提供了一套机制来管理和加载模块。在OSGi中,每个模块都有自己的类加载器,可以独立加载和管理类,从而打破双亲委派机制。
  3. Java SPI机制:Java SPI(Service Provider Interface)是一种标准的服务发现机制,在SPI中,服务的实现类通过在META-INF/services目录下的配置文件中声明,而不是通过类路径来查找。通过SPI机制,可以实现在不同的类加载器中加载不同的服务实现类,从而打破双亲委派机制。

需要注意的是,打破双亲委派机制可能会引入一些潜在的风险和问题,如类的冲突、不一致性等。在使用这些方法打破双亲委派机制时,需要谨慎考虑,并确保能够正确处理类的加载和依赖关系。

除了上述提到的方法,还有一些其他的方法可以打破双亲委派机制:

  1. 使用Java Instrumentation API:Java Instrumentation API允许在类加载过程中修改字节码,从而可以在类加载时修改类的加载行为,包括打破双亲委派机制。通过Instrumentation API,可以在类加载前修改类的字节码,使其加载时使用自定义的类加载器。
  2. 使用Java动态代理:Java动态代理机制可以在运行时生成代理类,并在代理类中实现特定的逻辑。通过使用动态代理,可以在类加载时动态生成代理类,并在代理类中实现自定义的类加载逻辑,从而打破双亲委派机制。
  3. 使用字节码操作库:可以使用字节码操作库,如ASM、Javassist等,来直接操作字节码,从而修改类的加载行为。通过这些库,可以在类加载时修改字节码,使其加载时使用自定义的类加载器。

在某些框架或场景中,为了满足特定的需求,可能会打破双亲委派机制。以下是一些常见的框架或场景:

  1. JavaEE容器:JavaEE容器(如Tomcat、WebLogic、WebSphere等)通常会使用自定义的类加载器来加载应用程序的类,以实现应用程序的隔离和独立性。这些容器会打破双亲委派机制,使用自定义的类加载器来加载应用程序的类。
  2. OSGi框架:OSGi(Open Service Gateway Initiative)是一种动态模块化的Java平台,它提供了一套机制来管理和加载模块。在OSGi中,每个模块都有自己的类加载器,可以独立加载和管理类,从而打破双亲委派机制。
  3. Java SPI机制:Java SPI(Service Provider Interface)是一种标准的服务发现机制,在SPI中,服务的实现类通过在META-INF/services目录下的配置文件中声明,而不是通过类路径来查找。通过SPI机制,可以实现在不同的类加载器中加载不同的服务实现类,从而打破双亲委派机制。
  4. 动态代理框架:一些动态代理框架,如CGLIB、Byte Buddy等,可以在运行时生成代理类,并在代理类中实现特定的逻辑。这些框架通常会使用自定义的类加载器来加载生成的代理类,从而打破双亲委派机制

总结

双亲委派机制是Java类加载器的一种工作机制,它的核心思想是在类加载的过程中,优先将加载请求委派给父类加载器,只有在父类加载器无法加载时,才由子类加载器尝试加载。

双亲委派机制的主要特点和优势包括:

  1. 避免类的重复加载:当一个类被加载后,它会被父类加载器缓存起来,避免了重复加载同一个类的问题,提高了类加载的效率。
  2. 类的隔离和安全性:通过双亲委派机制,不同的类加载器加载的类具有不同的命名空间,相同类名的类可以被不同的类加载器加载,实现了类的隔离和安全性。
  3. 保护核心类库的完整性:核心类库由启动类加载器加载,避免了用户自定义的类替换核心类库的情况,保护了核心类库的完整性。

总结起来:

  1. 双亲委派机制通过层级结构的类加载器组织,实现了类的共享、隔离和安全性。
  2. 它是Java类加载器的一种重要机制,为Java应用程序提供了良好的类加载环境。
  3. 然而,在某些特定的场景下,为了满足特定的需求,可能需要打破双亲委派机制,使用自定义的类加载器来加载类。
  4. 在使用自定义类加载器时,需要仔细评估和测试,确保能够正确处理类的加载和依赖关系。

本文已收录到我的面试小站 www.java2top.cn,【Java原创八股文面试网-助力你的大厂offer】

汇总收录各互联网大厂实时高频面经攻略(含详解)& 热点+原创项目🔥

其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

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

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

相关文章

python安装库

查看安装的库 按下开始r 输入cmd 查看python版本 查看python所有库 安装一个库 在pycharm里面查看库文件 在pycharm里面安装库 在anaconda里面安装库和查看库

Java练习题 2022 -4

皖北流行一种叫做“干瞪眼”的扑克牌游戏&#xff0c;使用的扑克牌牌面数值包括&#xff1a;A(1),2,3,4,5,6,7,8,9,T(10),J(11),Q(12),K(13)。这里10用T替换&#xff0c;暂时不考虑大鬼和小鬼。 两手牌的大小规则如下&#xff08;暂不考虑其他规则&#xff09;&#xff1a; a…

阿里云服务器—ECS快速入门

这里对标阿里云的课程&#xff0c;一步步学习&#xff0c;链接在下面&#xff0c;学习完考试及格即可获取阿里云开发认证和领取证书&#xff0c;大家可以看看这个&#xff0c;这里我当作笔记&#xff0c;记一下提升印象&#xff01; 内容很长&#xff0c;请耐心看完&#xff0…

视频特效制作软件 After Effects 2023 mac中文版介绍说明

After Effects 2023 mac是一款专业视频特效和动态图形设计软件。ae2023被广泛应用于电影、电视节目、广告和网络媒体等领域&#xff0c;可以创建各种令人惊叹的视觉效果。 在After Effects 2023中&#xff0c;用户可以使用强大的工具和功能来制作复杂的特效和动画。新版本引入了…

EASYX动画效果实现

eg1:绘制小球的动画效果 通过一下的代码实现小球从左向右移动效果&#xff0c;计算小球的移动速度和帧率实现移动效果平和造成视觉上的错觉 #include <stdio.h> #include <easyx.h> #include <iostream> #include <math.h> #define PI 3.14 // 1PI …

Word批量删除文档属性和个人信息方法图解

投标文件中设计敏感信息&#xff0c;在投标前必须删除&#xff0c;Word批量删除文档属性和个人信息方法图解&#xff1a; 右键word文件属性--详细信息&#xff0c;可以查看如下信息&#xff1b; 删除上述信息的办法&#xff1a; 1.打开word文件---文件 2.检查文档、检查文档 检…

Kubernetes的hostpath创建pv和pvc的验证---以部署halo博客系统为例

结论&#xff1a;hostapath作为一种存储类型是支持使用pv及pvc声明使用的。 缘由&#xff1a;最近在寻求云计算方向的运维管理岗位&#xff0c;周五晚上参加了一个头部大厂的西安岗位电面&#xff0c;面试人似乎不情愿作为本场考评的面试官&#xff0c;我在电子会议等了大约17分…

C++ 动态规划 DP教程 (一)思考过程(*/ω\*)

动态规划是一种思维方法&#xff0c;大家首先要做的就是接受这种思维方法&#xff0c;认同他&#xff0c;然后再去运用它解决新问题。 动态规划是用递推的思路去解决问题。 首先确定问题做一件什么事情&#xff1f; 对这件事情分步完成&#xff0c;分成很多步。 如果我们把整件…

【0基础学Java第三课】-- 运算符

3. 运算符 3.1 什么是运算符3.2 算术运算符3.2.1 **基本四则运算符&#xff1a;加减乘除模( - * / %&#xff09;**3.2.2 增量运算符 - * %3.2.3 自增/自减运算符 -- 3.3 关系运算符3.4逻辑运算符(重点)3.4.1 逻辑与 &&3.4.2 逻辑 ||3.4.3逻辑非 !3.4.4 短路求值 3.5 …

Lauterbach使用指南之RunTime功能

Lauterbach使用指南之RunTime功能 前言 首先&#xff0c;请问大家几个小小问题&#xff0c;你清楚&#xff1a; Lauterbach这个工具是干什么用的吗&#xff1f;在软件运行过程中如何测量两个运行point之间的runtime时间呢&#xff1f;Lauterbach的RunTime功能具体应当如何来操…

Linux中shell脚本的基础知识

目录 一、shell脚本的意义 二、如何创建shell脚本 三、如何执行shell脚本 四、如何对脚本进行调试 五、练习 一、shell脚本的意义 1、shell&#xff1a;脚本中命令的解释器 2、脚本的意义&#xff1a; 记录命令执行的过程和执行逻辑&#xff0c;以便以后重复执行脚本可以…

matlabR2021a正版免费使用

目录 matlab介绍&#xff1a; 安装&#xff1a; matlab介绍&#xff1a; MATLAB&#xff08;Matrix Laboratory的缩写&#xff09;是一种高级技术计算和编程环境&#xff0c;由MathWorks公司开发。它在科学、工程、数据分析和数学建模领域中广泛应用&#xff0c;为用户提供了…

【RTOS学习】互斥管理 | 调试 | 信息统计

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《RTOS学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 互斥管理 | 调试 | 信息统计 &#x1f349;互斥管理&#x1f330;屏蔽中断&#x1f330;暂停调度器…

VMware Horizon 8 2309 Enterprise虚拟桌面

VMware Horizon 8 2309 Enterprise虚拟桌面 一、虚拟桌面二、产品发布三、VMware Horizon 8 2309 Enterprise1.VMware Horizon 8 2309 Enterprise产品清单2.安装部署3. 优化工具总结 一、虚拟桌面 利用虚拟桌面和应用随时随地进行访问。 从云端进行管理 使用云端控制台和 Saa…

IO线程及相关函数

进程是资源分配的最小单位&#xff0c;线程是cpu调度的最小单位 一、概念&#xff1a; 线程指的是共享相同地址空间的多个任务 是一个轻量级的进程&#xff0c;为了提高系统的性能引入线程&#xff0c;线程和进程都参与统一的调度 在同一个进程中创建的线程共享该进程的地址空间…

预制菜配送小程序商城的效果如何

预制菜是近些年热度较高的新赛道&#xff0c;很多商家品牌入局&#xff0c;而投入到市场中也受到不少商家的喜欢&#xff0c;各种品牌和经销商层出不穷&#xff0c;目前各品牌主要以拓展市场和研究菜品为主&#xff0c;而线上无疑是很好的宣传销售渠道。 接下来让我们看看通过…

搭建gnn环境

1.无法激活 激活pytorch遇到报错usage: conda-script.py [-h] [--no-plugins] [-V] COMMAND ... conda-script.py: error: arg-CSDN博客 参考教程 【精选】手把手教你在windows10安装GNN相关环境&#xff08;torchtorch_geometricrdkitdeepchem&#xff09;_gnn环境相关的包-…

Docker Consul概述及构建

Docker Consul概述及构建 一、Consul概述1.1、什么是Consul1.2、consul 容器服务更新与发现1.3、服务注册与发现的含义1.4、consul-template概述1.5、registrator的作用 二、consul部署2.1、环境配置2.2、在主节点上部署consul2.3 、配置容器服务自动加入nginx集群2.3.1、安装G…

【Linux】:进程程序替换

进程程序替换 一.替换原理二.替换函数三.exec类函数 一.替换原理 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支)&#xff0c;子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时&#xff0c;该进程的用户空间代码和数据完全…

CleanMyMac X2024永久免费版mac电脑管家

日常使用中&#xff0c;很多用户忽略了Mac清除数据的重要性。当Mac运行速度越来越慢&#xff0c;发热严重&#xff0c;储存空间总是不足的时候&#xff0c;才意识到保持日常清理才是解决这些问题的根本。经常清理Mac&#xff0c;还有你意想不到的好处。 提高系统性能&#xff…