概述

    Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将她的class文件加载到内存生成的class对象。而且加载某个类的class文件时,java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式。

双亲委派机制的工作原理

     (1)如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行;
     (2)如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归请求最终将到达顶层的启动类加载器;
     (3)如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。



spring双亲委派 类的双亲委派机制_类加载器


双亲委派机制的优势

    • 1.避免类的重复加载

    • 2.保护程序安全,防止核心API被随意修改
    启动类加载器可以抢在标准扩展类装载器之前去装载类,而标准扩展类装载器可以抢在类路径加载器之前去装载那个类,类路径装载 器又可以抢在自定义类加载器之前去加载它。所以Java虚拟机先从最可信的Java核心API查找类型,这是为了防止不可靠的类扮演被信任的类,试想一 下,网络上有个名叫java.lang.Integer的类,它是某个黑客为了想混进java.lang包所起的名字,实际上里面含有恶意代码,但是这种 伎俩在双亲模式加载体系结构下是行不通的,因为网络类加载器在加载它的时候,它首先调用双亲类加载器,这样一直向上委托,直到启动类加载器,而启动类加载 器在核心Java API里发现了这个名字的类,所以它就直接加载Java核心API的java.lang.Integer类,然后将这个类返回,所以自始自终网络上的 java.lang.Integer的类是不会被加载的。

    •3.保证核心API包的访问权限
    但是如果这个移动代码不是去试图替换一个被信任的类(就是前面说的那种情况),而是想在一个被信任的包中插入一个全新的类型,情况会怎样呢?比如一个名为 java.lang.Virus的类,经过双亲委托模式,最终类装载器试图从网络上下载这个类,因为网络类装载器的双亲们都没有这个类(当然没有了,因为 是病毒嘛)。假设成功下载了这个类,那你肯定会想,Virus和lang下的其他类痛在java.lang包下,暗示这个类是Java API的一部分,那么是不是也拥有修改Java.lang包中数据的权限呢?答案当然不是,因为要取得访问和修改java.lang包中的权 限,java.lang.Virus和java.lang下其他类必须是属于同一个运行时包的,什么是运行时包?运行时包是指由同一个类装载器装载的、属 于同一个包的、多个类型的集合。考虑一下,java.lang.Virus和java.lang其他类是同一个类装载器装载的吗?不是的!java.lang.Virus是由网络类装载器装载的!

双亲委派机制在SPI中的应用

     1.某个应用程序由双亲委派机制找到引导类加载器,首先调用rt.jar包中的SPI核心,但由于SPI核心当中有各种各样的接口需要被实现(这里指具体的服务提供商),这里我们已JDBC.jar为例,jdbc.jar可以为我们提供具体的实现。

     2.那么这时我们需要反向委托,找到线程上下文类加载器去加载jdbc.jar

     3.线程上下文类加载器属于系统类加载器



spring双亲委派 类的双亲委派机制_java_02


Peace!