iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >何为双亲委派原则
  • 787
分享到

何为双亲委派原则

2024-04-02 19:04:59 787人浏览 安东尼
摘要

本篇内容主要讲解“何为双亲委派原则”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“何为双亲委派原则”吧!我敢打赌大家在开发过程中经常碰到一些类加载的问题,比如:C

本篇内容主要讲解“何为双亲委派原则”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“何为双亲委派原则”吧!

我敢打赌大家在开发过程中经常碰到一些类加载的问题,比如:

ClassNotFoundException

Cause: java.lang.ClassNotFoundException: Cannot find class: com.cc.A

NoClassDefFoundError

Cause: java.lang.NoClassDefFoundError: Cannot find class: com.cc.A

上述问题均和java类加载有关,如果不清楚JVM中类加载的原理,上述问题会让人郁闷至极,侥幸在网上找到解决方案也只是暂时解决问题,后续在另外的场景中碰到又会继续懵逼。

我这篇文章将对 Java  类加载器的双亲委派加载原理进行阐述,并结合实例程序深究类的双亲委派加载机制,大家彻底了解掌握类加载原理,清楚了类加载原理后,碰到上述类似问题就能快速解决,并在后续开发中避免类似问题。

什么是Java类加载?

java类加载器负责将编译好的 Java class 件加载到 Java  虚拟机(JVM)中的运行时数据区中,供执行引擎调用。

java类加载在JVM体系结构中的位置如图所示:

何为双亲委派原则

jvm体系结构原图

没有类加载机制,编写的java程序就没法在JVM中运行,因此掌握java类加载是非常重要的。

JVM类加载层级关系

执行java程序时,会启动一个JVM进程,JVM在启动时会做一些初始化操作,比如获取系统参数等等,然后创建一个启动类加载器,用于加载JVM运行时必须的一些类到内存中,同时也会创建其他两个类加载器扩展类加载器和系统类加载器。

启动类加载器、扩展类加载器和系统类加载器之间的关系如下图所示:

何为双亲委派原则

jvm内置classLoader

  • **启动类加载器:**java虚拟机启动后创建的第一个类加载器,由c++语言实现,所以我们在java代码中查看其信息时,看到的均为null。

  • 扩展类加载器:由启动类加载器加载,并将扩展类加载器中的parent的值设置为null(表示指向启动类加载器),同时继承自URLClassLoader。

  • 系统类加载器:由启动类加载器加载,并将系统类加载期中的parent的值设置为上述创建的扩展类加载器。,同时继承自URLClassLoader。

在代码中可以通过如下方式查看类加载中的parent指向:

何为双亲委派原则

代码查看类加载器的parent

注意:这里的parent不是java的继承机制,而是类加载器中的一个实例属性,用于在类加载时的委托对象,parent属性定义在其所继承的ClassLoader中,定义如下所示。

public abstract class ClassLoader {    ....................     // The parent class loader for delegation     private final ClassLoader parent;

JVM类加载的默认加载路径

每种类型的类加载器默认都会有自己的加载路径,启动类加载器、扩展类加载器和系统类加载器的默认加载路径如下图所示:

何为双亲委派原则

三种类加载器的加载路径

如上图所示:

1、启动类加载器(BootClassLoader)由C++语言编写,负责在JVM启动时加载jdk自身的一些核心class类(jar包形式)到JVM中,加载时寻找资源的路径由只读系统属性:”sun.boot.class.path“  指定,一般为:”JAVA_HOME/jre/classes“目录(在该目录下只能放class文件,jar包形式文件不生效)。

查看启动类加载类加载路径可以通过获取系统属性:”sun.boot.class.path“进行查看,如图所示:

何为双亲委派原则

lancher中设置启动类加载路径

何为双亲委派原则

启动类加载器加载路径

2、扩展类加载器(ExtClassLoader),负责加载位于系统属性:"java.ext.dirs"指向的目录下加载class文件(jar包或者直接class文件形式)到JVM中,比如通常ext类加载路径为:”$JAVA_HOMEx/jre/lib/ext“  。

支持在JVM启动之前进行修改路径,运行中修改路径不生效,扩展类路径中仅支持jar包的加载。

查看扩展类加载器的类加载路径可以通过获取系统属性:”java.ext.dirs“进行查看或向上转型为URLClassLoader(上面说扩展类加载器继承自URLClassLoader),查看位于父类URLClassLoader中urls属性的方式进行查看,如图所示:

何为双亲委派原则

扩展类加载器路径

3、系统类加载器(AppClassLoader),负责加载应用classpath路径下的class文件(jar包或者直接class文件形式)到JVM中,当系统中没有设置classpath路径时,默认加载当前路径下的class文件。

查看系统类加载器的类加载路径可以通过获取系统属性:”java.class.path“进行查看或向上转型为URLClassLoader上面说扩展类加载器继承自URLClassLoader),查看位于父类URLClassLoader中urls属性的方式进行查看,如图所示:

何为双亲委派原则

系统类加载路径

JVM类加载双亲委托机制

JVM加载class类文件到虚拟机时,默认首先采用系统类加载器去加载用到的class类,采用的是双亲委托加载机制。

所谓双亲委托,顾名思义,就是当前类加载器(以系统类加载器为例)在加载一个类时,委托给其双亲(注意这里的双亲指的是类加载器中parent属性指向的类加载器)先进行加载。

双亲类加载器在加载时同样委托给自己的双亲,如此反复,直到某个类加载器没有双亲为止(通常情况下指双亲为null,也即为当前的双亲为扩展类加载器,其parent为启动类加载器),然后开始在依次在各自的类路径下寻找、加载class类。

如下图所示:

何为双亲委派原则

双亲委派

双亲委托加载实例实例

采用JDK版本

java version "1.8.0_261" Java(TM) SE Runtime Environment (build 1.8.0_261-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode)

本实例涉及到两个类:TestMain.java 和  A.java,期中TestMain为启动类,在启动类中调用类A中的方法执行进行输出,分别输出启动类和被依赖类的类加载器信息,类定义如下所示:

何为双亲委派原则

A_java

何为双亲委派原则
TestMain

我们将两个java文件拷贝到某个目录下,在我本地比如放在E:\java_app目录下,windows下打开命令行窗口,切换到E:\java_app,对当前java文件进行编译,执行命令javac  TestMain.java。

此时会在当前目录下生产对应的class文件(这里只需要对TestMain执行编译命令,因为TestMain依赖了A,所以Jdk编译器就会自动先去编译依赖的A),如图所示:

何为双亲委派原则

编译命令

接下来我们将观察java类加载机制是怎样实现双亲委托加载的。

委托给扩展类加载器加载

由于扩展类在自身类路径下加载只支持寻找jar包的方式,因此我们通过工具将A.class文件打包进A.jar。

然后将A.jar放置到扩展类加载路径:$JAVA_HOME/jre/lib/ext,同时保留当前目录中的A.class文件。如图所示:

何为双亲委派原则

扩展委派

此时在当前目录:E:\java_app下仍然保留有A.class文件,在扩展类加载器路径下多了一个包含了A.class的A.jar文件,在当前目录下执行java命令执行TestMain,命令为:java  TestMain,输出如下所示:

何为双亲委派原则

扩展委派结果

由上图输出结果可知,class  A虽然在系统类加载器的加载路径中,但由于类加载的委托机制,A首先将由系统类加载器委托给其双亲扩展类加载器进行加载,刚好在扩展类加载器的加载路径中包含了A.class(包含在A.jar中),所以A最终由扩展类加载器进行了加载。

委托给启动类加载器进行加载

通常情况下,普通类的加载不应该委托给启动类加载器进行加载,因为前面说过启动类加载器由C++实现,在java虚拟机启动时生成的,在java环境中获取她的信息均为null。

本实例为了探究类加载的双亲委托机制,所以特意将构造一个将普通类委托给其加载的场景。

前面在讲到启动类加载器加载路径时指出了启动类加载器的加载路径由只读系统属性”sun.boot.class.path“  指定,且仅支持加载该目录下固定的jar文件。

在jdk8中还有”$JAVA_HOME/jre/classes“目录也是启动类加载器加载的路径(该路径默认可能不存在,可以手工创建一个),在该目录下只能放class文件,jar包形式文件不生效。

因此,本实例程序将当前目录下的A.class文件拷贝到启动类加载器的类路径:”$JAVA_HOME/jre/classes“中,同时保留当前目录中的A.class文件,也保留扩展类加载器类路径中的A.jar。

类存放路径如图所示:

何为双亲委派原则

委派启动

在当前目录:E:\java_app目录下执行命令运行TestMain,命令为:java TestMain,输出如下所示:

何为双亲委派原则

委派启动结果

由上图输出结果可知,class  A虽然在系统类加载器的加载路径中,也存在扩展类加载器的加载路径中,但由于类加载的委托机制,A首先将由系统类加载器委托给其双亲扩展类加载器进行加载。

扩展类加载器又会继续进行委托加载(实际上因为扩展类加载器的parent:启动类加载器为null,所以此时的委托动作实际上就是去启动类加载器的加载路径中寻找class  A),最终由启动类加载进行了A的加载。

双亲委托加载方向

类加载器在加载类时,只能向上递归委托其双亲进行类加载,而不可能从双亲再反向委派当前类加载器来进行类加载。

在中国象棋中,卒子过河之后的行走轨迹永远只能是前进或者左右平移,可以很形象的比作双亲委托类加载的这种方向性。

  • 卒子过河比喻当前类加载器委派其双亲加载了某个类。这个类的后续依赖的加载已经和当前类加载器没有关系。

  • 过河之后的卒子只能前进,表示双亲在加载类的依赖类时,只能继续递归进行双亲委派。

  • 左右平移表示双亲在递归双亲委派加载失败后,在双亲类加载器自己的加载路径中进行加载。

为了表明委派具有方向性,我们继续拿上面的TestMain.class和A.class两个类做实验。

上述委托实例中我们的场景时是:TestMain中依赖了A,我们将A通过双亲委托方式进行了加载,本次实验中,我们将TestMain委托给双亲加载。

参照上述的操作步骤,将TestMain.class打进TestMain.jar中,放到扩展类加载器的加载路径中,同时也保留TestMain.class到当前目录,如下图所示:

何为双亲委派原则

委派加载顺序1

切换到当前应用目录,执行java命令运行程序:java TestMain,执行结果如下所示:

何为双亲委派原则

委派顺序执行结果

如上图所示,出现错误了,TestMain被扩展类加载器加载了,依赖的A却没有能被加载到。

原因就是上述说的委派加载具有方向性导致的:

1、运行java命令执行TestMain程序时,系统类加载器准备加载TestMain,根据双亲委派机制,先委派给其双亲进行加载,最后,双亲扩展类加载器在其加载路径中的TestMain.jar中找到了TestMain.class,完成了TestMain的加载。

2、TestMain中依赖了A,此时,会根据加载了TestMain的类加载器:扩展类加载器去加载A,加载方式根据委托机制递归委托给双亲加载,扩展类加载器的双亲为启动类加载器,在启动类加载器的加载路径中不存在A,加载失败,此时由扩展类加载器在自己的加载路径中加载A,也因为加载路径中没有A.class存在,A.class存在于系统类加载器的加载路径中,但是扩展类加载器不会再返回去委托系统类加载器进行加载,所以直接抛出加载失败异常,出现了上述的错误。

到此,相信大家对“何为双亲委派原则”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 何为双亲委派原则

本文链接: https://www.lsjlt.com/news/83508.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 何为双亲委派原则
    本篇内容主要讲解“何为双亲委派原则”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“何为双亲委派原则”吧!我敢打赌大家在开发过程中经常碰到一些类加载的问题,比如:C...
    99+
    2024-04-02
  • 详解jvm双亲委派机制
    目录双亲委派机制类加载器种类双亲委派机制为什么要设计双亲委派机制?自定义类加载器打破双亲委派机制双亲委派机制 ​记录一下JVM的双亲委派机制学习记录。 类加载器种类 ​当我们运行某一...
    99+
    2022-11-13
    jvm双亲委派机制 jvm双亲委派
  • JVM要双亲委派的原因及如何打破它
    目录一、类加载器二、双亲委派机制2.1什么是双亲委派2.2为什么要双亲委派?三、破坏双亲委派四、Class.forName默认使用的类加载器五、线程上下文类加载器六、要点回顾一、类加...
    99+
    2024-04-02
  • tomcat怎么打破双亲委派机制
    在Tomcat中打破双亲委派机制并不推荐,因为双亲委派机制是Java类加载机制的重要组成部分,可以提高安全性和稳定性。如果一定要打破...
    99+
    2024-04-02
  • java双亲委派机制怎么实现
    Java的双亲委派机制是通过ClassLoader来实现的。ClassLoader是Java虚拟机中负责加载类的机制,它按照一定的规...
    99+
    2023-10-08
    java
  • ClassLoader双亲委派模式作用详解
    目录前言ClassLoader的作用ClassLoader的种类如何实现双亲委派模式小测试前言 我们的面试中经常会遇到关于ClassLoader的问题,但是我们的日常开发中又没有直接...
    99+
    2022-11-13
    ClassLoader双亲委派 ClassLoader 模式
  • java双亲委派机制怎么应用
    Java的双亲委派机制是一种类加载器的工作方式,用于保护Java应用程序的安全性和稳定性。它的应用主要包括以下几个方面:1. 自定义...
    99+
    2023-10-11
    java
  • java双亲委派机制有什么作用
    Java双亲委派机制是一种类加载机制,其作用主要有两个方面: 避免类的重复加载:当一个类加载器需要加载一个类时,它会先委托给其父...
    99+
    2024-04-02
  • 浅谈一下Java的双亲委派模式
    目录类加载器是什么?类加载器分类双亲委派模型工作流程双亲委派模型好处说起双亲委派模型,不得不说一下类加载器。 类加载器是什么? 当我们编译Java类时,JVM会创建与平台和机器无关的...
    99+
    2023-05-18
    java 模型 java双亲委派
  • JVM双亲委派模型知识详细总结
    目录一、简介二、双亲委派的意义三、JVM提供的类加载器四、执行类加载的五种方式五、自定义类加载器六、总结一、简介 除了顶层的启动类加载器(Bootstrap ClassLoader)...
    99+
    2024-04-02
  • Java虚拟机之双亲委派机制详解
    目录一、原理二、作用三、沙箱安全机制四、补充内容总结Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象...
    99+
    2024-04-02
  • Java的三次破坏双亲委派模型是什么
    这篇文章主要介绍“Java的三次破坏双亲委派模型是什么”,在日常操作中,相信很多人在Java的三次破坏双亲委派模型是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java的三次破坏双亲委派模型是什么”的疑...
    99+
    2023-06-15
  • Java虚拟机中的双亲委派机制怎么理解
    Java虚拟机中的双亲委派机制怎么理解,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类...
    99+
    2023-06-22
  • JVM的类加载器和双亲委派模式你了解吗
    目录类加载器1、启动类加载器2、拓展类加载器3、应用程序类加载器4、双亲委派模式5、自定义类加载器5.1、使用场景5.2、步骤总结类加载器 Java虚拟机设计团队有意把类加载阶段中的...
    99+
    2024-04-02
  • JVM的类加载器和双亲委派模式实例分析
    这篇文章主要讲解了“JVM的类加载器和双亲委派模式实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JVM的类加载器和双亲委派模式实例分析”吧!类加载器Java虚拟机设计团队有意把类加载...
    99+
    2023-06-29
  • Tomcat打破双亲委派机制实现隔离Web应用的方法
    目录Tomcat类加载器的层次结构WebAppClassLoaderSharedClassLoaderCatalinaClassLoaderCommonClassLoaderSpri...
    99+
    2024-04-02
  • Java虚拟机类加载器之双亲委派机制模型案例
    1. 双亲委派模型是什么? 当某个类加载器需要加载某个.class字节码文件时,它首先把这个任务委托给它的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类...
    99+
    2024-04-02
  • 自定义类加载器以及打破双亲委派模型解析
    目录1 自定义类加载器2 打破双亲委派模型1 自定义类加载器自定义类加载器的代码很简单,只需要继承ClassLoader类,覆写findClass方法即可其默认实现是会抛出...
    99+
    2022-11-21
    自定义类加载器 双亲委派模型
  • 浅谈Tomcat如何打破双亲委托机制
    目录JVM的类加载器Tomcat的类加载器findClassloadClass我们经常会遇到ClassNotFound异常,表明JVM在尝试加载某类时失败了。 要解决这个异常,你得...
    99+
    2024-04-02
  • Tomcat是如何打破双亲委托机制的
    本篇内容介绍了“Tomcat是如何打破双亲委托机制的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录JVM的类加载器Tomcat的类加载器...
    99+
    2023-06-20
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作