您的位置: 游戏资讯 > 游戏问答

双亲委派机制及使用原因,双亲委派机制解决了什么问题

来源:网络 浏览:56 2022-11-10 04:29:01

我想你们在开发过程中经常遇到类路问题。 例如:

classnotfoundexceptioncause:Java.lang.classnotfoundexception:cannotfindclass:com.cc.anoclassdefounderrorcause:cause 幸运的是,在网上找到解决方案也只是暂时解决问题,之后遇到别的场景又继续无知。 本文介绍了Java类加载器的父母代理加载的原理,并结合实例程序详细研究了类的父母代理加载机制。 大家在全面了解类加载原理,了解类加载原理后,如果遇到上述问题,可以迅速解决,并在后续开发中避免类似问题。

什么是Java类的加载? java类加载器将编译的java类组件加载到java虚拟机( JVM )中的运行时数据区并执行引擎调用。 JVA类在JVM架构中的加载位置如图所示。

双亲委派机制及使用原因,双亲委派机制解决了什么问题

了解java类的加载非常重要,因为如果没有类的加载机制,编写的java程序就无法在JVM上运行。

运行JVM类的负载级别相关java程序将启动JVM进程,JVM将在启动时执行初始化操作,如获取系统参数。 然后,创建一个启动类加载器,用于将运行JVM所需的一些类加载到内存中,并创建其他两个类加载器扩展类加载器和系统类加载器。 启动类加载器、扩展类加载器和系统类加载器之间的关系如下图所示。

启动类加载器:这是自java虚拟机启动后创建的第一个类加载器,使用c语言实现,因此当您在java代码中查看其信息时,所有类加载器都将显示为空。 扩展类加载器:由启动类加载器加载,将扩展类加载器的parent值设置为null。 这意味着它指向启动类加载器,从URLClassLoader继承。 系统类加载器:由启动类加载器加载,用于将系统类加载器的部件的值设置为上面创建的扩展类加载器。 也从URLClassLoader继承。 在代码中,可以按如下方式显示类加载的部件点:

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

ublicabstractclassclassloader ( ./theparentclassloaderfordelegationprivatefinalclassloaderparent; JVM类加载器的缺省加载路径每种类型的类加载器缺省都有自己的加载路径,启动类加载器、扩展类加载器和系统类加载器的缺省加载路径如下图所示。

如上图所示: 1、启动类加载器( BootClassLoader )用c语言编写,在JVM启动时负责将jdk自身的核心类( jar包格式)加载到JVM中。 加载时查找资源的路径为只读系统属性) )要显示由sun.boot.class.path指定的启动类加载类加载路径,请单击系统属性“sun.boot.sun.boot.class.path”,如图所示

2、扩展类加载器( ExtClassLoader )将系统属性( java.ext.dirs )指向的目录下的class文件( jar包或直接为class文件格式)加载到JVM中例如,普通ext类的加载路径是) $Java_homer JVM启动前更改路径是受支持的。 在运行过程中更改路径没有效果。 扩展类路径仅支持加载jar包。 要查看扩展类加载器的类加载路径,请获取系统属性: java.ext.dirs并将其显示在URLClassLoader中,或者将其上转换为URLClassLoader,如图所示。 扩展类加载器从URLClassLoader继承。 检查父类的URLClassLoader中urls属性的显示方式。

3、系统类加载器( AppClassLoader )负责将APP应用程序的classpath路径下的class文件( jar包或直接class文件格式)加载到JVM中。 如果系统未设置classpath路径,则缺省情况下将加载当前路径下的class文件。 要查看系统类加载器的类加载路径,请获取系统属性: java.class.path并将其显示在URLClassLoader中,或升级到URLClassLoader,如图所示

JVM类加载父母委托机制JVM向虚拟机加载class类文件时,缺省情况下先用系统类加载器加载要使用的class类,然后采用父母委托加载机制。 来自父母的请求,顾名思义,就是当前类加载器(以系统类加载器为例,加载一个类时,请求父母)这里的父母就是类加载器的parent属性所指的类加载器父母类加载器在加载时也委托自己的父母,重复进行直到某个类加载器没有父母为止(通常父母为null,即当前父母为扩展类加载器,其parent为启动类加载器),在各自的类路径下为class 如下图所示。

父母请求用JDK版本加载实例

Javaversion'1.8.0_261'Java(TM ) seruntimeenvironment ) build1.8.0_261-B12 ) JavaHotspot ) TM ) 64-bit sssstm

本示例说明TestMain.java和A.java这两个类。 其中TestMain是启动类,它在启动类中调用并输出类a的方法执行,并分别输出启动类和依赖类的类加载器信息。 类定义如下。

我们把两个java文件复制到一个目录下,放在我的本地比如E:\java_app目录下,在windows下打开命令行窗口,在E:\java_app上将创建与当前目录相对应的class文件。 在这里,您只需对TestMain运行编译命令,如图所示。 由于TestMain依赖于a,因此Jdk编译器会自动先编译依赖的a。

其次,观察java类加载机制如何实现父母委托加载。

使用工具将A.class文件打包为A.jar,因为委托给扩展类加载器的扩展类只支持在用自己的类路径加载时查找jar包。 然后,将A.jar放在扩展类的加载路径$JAVA_HOME/jre/lib/ext中,以保留当前目录中的A.class文件。 如图所示:

当前目录: E:\java_app下保留A.class文件,扩展类加载器路径下添加了包含A.class的A.jar文件。 在当前目录下运行java命令并运行TestMain。 命令应如下所示:

从上图的输出结果可以看出,class A位于系统类加载器的加载路径上,但是为了类加载的委托机制,a首先从系统类加载器委托父母的扩展类加载器进行加载,正好在扩展类加载器的加载路径上输入a

通常,要求启动类加载器加载类时,不应该要求启动类加载器进行加载。 如上所述,启动系统加载器由c实现,在java虚拟机启动时生成,因为在java环境中获取她的信息都是空的。 在本例中,为了探索来自类加载的父母的委托机制,特意构建了委托加载一般类的场景。 对于上述启动类加载器的加载路径,启动类加载器的加载路径由只读系统属性“sun.boot.class.path”指定,并且位于该目录中的固定jar文件jdk8还包含$JAVA_HOME/jre/classes目录。 此目录只能包含class文件,jar包格式的文件无效。 默认情况下,此路径可能不存在。 因此,该实例程序会将当前目录下的A.class文件复制到启动类加载器的类路径“$JAVA_HOME/jre/classes”中,并将其放入当前目录中的A.class 类的存储路径如下:

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

从上图的输出结果可以看出,class A既存在于系统类加载器的加载路径中,也存在于扩展类加载器的加载路径中,但是为了类加载的委托机制,a首先从系统类加载器委托父母的扩展类加载器进行加载。 扩展类加载器还继续委托加载,最终启动类加载器的部件:启动类加载器为空,所以此时的委托操作实际上是去启动类加载器的加载路径中寻找class A。 ),最终由启动类加载器进行a的加载。

请求父母加载类的方向类加载器在加载类时,只能递归地请求父母加载类,而不能通过从父母反向委托当前类加载器来进行类的加载。 在中国象棋中,毕业生过河后的行走轨迹只能永远前进或左右移动,可以想象成父母向班级要求加载的方向。

毕业生过河比喻现在的类加载器任命父母加载某个类。 此类随后依赖的加载与当前类加载器无关。 过河后的毕业生只能前进,表示父母加载类依赖类时,只能递归地继续委托父母。 左右平移表示父母在递归父母委托加载失败后,使用父母类加载器自身的加载路径进行加载。 为了表明委托是有方向的,我们将继续实验上面的TestMain.class和A.class这两个类。 在上述的委托例子中,显示了a依赖于TestMain,通过将a委托给父母进行加载的情况,但是在这次的实验中,将TestMain委托给父母进行加载。 使用上述过程,在TestMain.jar中输入TestMain.class,并将TestMain.class保存到扩展类加载器的加载路径中,如下图所示。

切换至当前APP应用程序目录,然后运行java命令可执行文件“java测试主”。 执行结果如下。

如上图所示,发生了错误。 TestMain已加载到扩展类加载器中,但未加载相关的a。 这是因为上述委托加载具有方向性。 1、运行java命令运行TestMain程序时,系统类加载器准备加载TestMain,根据父母委托机制,先将加载委托给父母,最后父母扩展类加载器在其加载路径中的TTP 在这种情况下,a由加载了TestMain的类加载器:扩展类加载器加载。 加载方式通过委托机制递归委托给父母。 扩展类加载器的父母是启动类加载器,如果启动类加载器的加载路径中不存在a,且加载失败,则扩展类加载器会将a加载到自己的加载路径中。 加载路径中不存在A.class,而A.class存在于系统类加载器的加载路径中,但是由于扩展类加载器返回并不要求系统类加载器进行加载,因此直接抛出加载失败的异常,并出现上述错误。

此次大致介绍了java类加载在整个JVM中的作用,详细介绍了JVM中启动类加载器、扩展类加载器、系统类加载器的关系,并结合实例进行了类加载来自父母的代理理解了java从父母那里代理加载的原理后,就可以在之后的程序开发设计中掌握程序动态设计的高级技能,开发出更优秀的产品。

资料来源: https://MP.weixin.QQ.com/s/6nj-6 CDL w6 tfy swv 5zb3iw

微信公众号:三太子青丙

和平精英体验服官网「V3.02」IOS版

和平精英体验服官网「V3.02」IOS版

  • 分类:资讯阅读
  • 大小:17MB
  • 语言:简体中文
  • 版本:V3.02