Java-JVM(三)------双亲委派模型 今天药忘吃喽~ 2021-12-19 01:43 257阅读 0赞 ## 一、类加载器是什么 ## 类加载器的工作是将.class文件加载到内存中,在方法区创建数据结构,并在堆中创建类的对象以便调用方法区的方法。 JAVA提供了三种类加载器: 一.**启动类加载器**(Bootstrap.ClassLoader),加载<JAVA\_HOME>/lib路径下的核心类库。 二.**扩展类加载器**(Extending.ClassLoader),加载<JAVA\_HOME>/lib/ext路径下的扩展类库。 三.**应用类加载器**(Application.ClassLoader),加载当前类路径或者导入的类库路劲下的类库。应用类加载器可以自定义。 这儿有一个父类加载器的概念,启动类加载器是扩展类加载器的父类,而扩展类加载器是应用类加载器的父类。 ## 二、双亲委派模型的工作过程是: ## > 1、如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。 > 2、每一个层次的类加载器都是如此。因此,所有的加载请求最终都应该传送到顶层的启动类加载器中。 > 3、只有当父加载器反馈自己无法完成这个加载请求时(搜索范围中没有找到所需的类),子加载器才会尝试自己去加载。 比如 1.首先应用类加载器会收到加载类的请求,收到请求后不立即加载,而是调用其父类加载器即扩展类加载器去加载。 2.扩展类加载器收到加载请求后也不会立即加载,而是调用其父类加载器启动类加载器去加载。 3.启动类加载器收到加载请求后,会去<JAVA\_HOME>/lib路径下寻找需要加载的类,若找到则加载,若找不到则回退请求其子类加载器即扩展类加载器去加载。 4.扩展类加载器收到请求后,会去<JAVA\_HOME>/lib/ext路径下寻找需要加载的类,若找到则加载,若找不到则回退请求其子类加载器即应用类加载器去加载。 5.应用类加载器收到请求后,会去当前类路径或者导入类库的路径下寻找需要加载的类,若找到则加载,若找不到则抛出ClassNotFoundException异常。 ## 三、双亲委派模式优势 ## 1:、避免类的重复加载 Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。 2、安全因素 java核心api中定义类型不会被随意替换,假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。 ## 四、双亲委派模型的破坏 ## 1.第一次破坏 由于双亲委派模型是在JDK1.2之后才被引入的,而类加载器和抽象类java.lang.ClassLoader则在JDK1.0时代就已经存在,面对已经存在的用户自定义类加载器的实现代码,Java设计者引入双亲委派模型时不得不做出一些妥协。 在此之前,用户去继承java.lang.ClassLoader的唯一目的就是为了重写loadClass()方法,因为虚拟机在进行类加载的时候会调用加载器的私有方法loadClassInternal(),而这个方法唯一逻辑就是去调用自己的loadClass()。 2.第二次破坏 双亲委派模型的第二次“被破坏”是由这个模型自身的缺陷所导致的,双亲委派很好地解决了各个类加载器的基础类的同一问题(越基础的类由越上层的加载器进行加载),基础类之所以称为“基础”,是因为它们总是作为被用户代码调用的API,但世事往往没有绝对的完美。 如果基础类又要调用回用户的代码,那该么办? 一个典型的例子就是JNDI服务,JNDI现在已经是Java的标准服务, 它的代码由启动类加载器去加载(在JDK1.3时放进去的rt.jar),但JNDI的目的就是对资源进行集中管理和查找,它需要调用由独立厂商实现并部署在应用程序的ClassPath下的JNDI接口提供者的代码,但启动类加载器不可能“认识”这些代码。 为了解决这个问题,Java设计团队只好引入了一个不太优雅的设计:线程上下文类加载器(Thread Context ClassLoader)。这个类加载器可以通过java.lang.Thread类的setContextClassLoader()方法进行设置,如果创建线程时还未设置,他将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那这个类加载器默认就是应用程序类加载器。 有了线程上下文加载器,JNDI服务就可以使用它去加载所需要的SPI代码,也就是父类加载器请求子类加载器去完成类加载的动作,这种行为实际上就是打通了双亲委派模型层次结构来逆向使用类加载器,实际上已经违背了双亲委派模型的一般性原则,但这也是无可奈何的事情。Java中所有涉及SPI的加载动作基本上都采用这种方式,例如JNDI、JDBC、JCE、JAXB和JBI等。 3.第三次破坏 双亲委派模型的第三次“被破坏”是由于用户对程序动态性的追求导致的,这里所说的“动态性”指的是当前一些非常“热门”的名词:代码热替换、模块热部署等,简答的说就是机器不用重启,只要部署上就能用。 OSGi实现模块化热部署的关键则是它自定义的类加载器机制的实现。每一个程序模块(Bundle)都有一个自己的类加载器,当需要更换一个Bundle时,就把Bundle连同类加载器一起换掉以实现代码的热替换。在OSGi幻境下,类加载器不再是双亲委派模型中的树状结构,而是进一步发展为更加复杂的网状结构,当受到类加载请求时,OSGi将按照下面的顺序进行类搜索: 1)将java.*开头的类委派给父类加载器加载。 2)否则,将委派列表名单内的类委派给父类加载器加载。 3)否则,将Import列表中的类委派给Export这个类的Bundle的类加载器加载。 4)否则,查找当前Bundle的ClassPath,使用自己的类加载器加载。 5)否则,查找类是否在自己的Fragment Bundle中,如果在,则委派给Fragment Bundle的类加载器加载。 6)否则,查找Dynamic Import列表的Bundle,委派给对应Bundle的类加载器加载。 7)否则,类加载器失败。
相关 双亲委派模型 双亲委派模型(图解) ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9 冷不防/ 2022年11月10日 10:43/ 0 赞/ 188 阅读
相关 双亲委派模型 一 定义与本质 类加载器用来把类加载到 Java 虚拟机中。从 JDK1.2 版本开始,类的加载过程采用双亲委派机制,这种机制能更好地保证 Java 平台的安全。 1 左手的ㄟ右手/ 2022年09月06日 14:19/ 0 赞/ 211 阅读
相关 双亲委派模型 说道双亲委派模型,就要从类加载器说起。。。。。。。。。。。 [Java][]虚拟机类加载过程是把Class类文件加载到内存,并对Class文件中的数据进行校验、转换解析和初始 亦凉/ 2022年07月12日 13:26/ 0 赞/ 224 阅读
相关 双亲委派模型 其实,双亲委派模型并不复杂。自定义类加载器也不难!随便从网上搜一下就能搜出一大把结果,然后`copy`一下就能用。但是,如果每次想自定义类加载器就必须搜一遍别人的文章,然后复制 落日映苍穹つ/ 2022年05月09日 16:56/ 0 赞/ 242 阅读
相关 双亲委派模型 双亲委派模型 类与类加载器 双亲委派模型 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到 野性酷女/ 2022年03月10日 14:28/ 0 赞/ 261 阅读
相关 Java-JVM(三)------双亲委派模型 一、类加载器是什么 类加载器的工作是将.class文件加载到内存中,在方法区创建数据结构,并在堆中创建类的对象以便调用方法区的方法。 JAVA提供了三种类加载器: 一 今天药忘吃喽~/ 2021年12月19日 01:43/ 0 赞/ 258 阅读
相关 双亲委派模型 双亲委派模型 双亲委派模型简介 双亲委派模型实现源码分析 双亲委派模型的好处 双亲委派模型简介 每一个类都有一个对应它的类加载器。系统中的类加载 不念不忘少年蓝@/ 2021年11月10日 14:28/ 0 赞/ 625 阅读
相关 双亲委派模型 双亲委派模型(Since JDK.2): ![这里写图片描述][70] 从虚拟机的角度来看,类加载器主要分为启动类加载器(Bootstrap Classloader)和 £神魔★判官ぃ/ 2021年09月26日 14:36/ 0 赞/ 593 阅读
相关 双亲委派模型 围绕这四个问题去回答一下: 1. 什么是双亲委派模型 2. 为什么会有双亲委派模型 3. 可以打破双亲委派模型? 4. 为什么要打破双亲委派模型? 一、 ╰+攻爆jí腚メ/ 2021年09月25日 11:08/ 0 赞/ 370 阅读
还没有评论,来说两句吧...