类加载器及其委托机制的深入分析

Java虚拟机可以安装多个类加载器,系统默认三个主要的类加载器,每个加载器负责加载特定位置的类:

BootStrap,ExtClassLoader,AppClassLoader。

类加载器本身也是一个Java类,因为其他Java类的类加载器本身也要被类加载器加载,所以肯定有一个类加载器不是Java类,这便是BootStrap,BootStrap嵌套在JVM内核中。Java虚拟机中所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载器。

当Java虚拟机要加载一个类时,首先由当前线程的类加载器去加载线程中的第一个类,如果类A引用了类B,Java虚拟机将使用加载类A的类加载器来加载类B,当然,也可以通过直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。

每个类加载器加载 类时,又先委托给其上级类加载器,当所有祖宗类加载器都没有加载到类,则会回到发起者类加载器,如果还加载不了,则抛出ClassNotFoundException,而不会去寻找发起者的儿子去加载,因为没有getChild()方法。看图:

当Java虚拟机要加载一个类时,一般来说,一个加载请求由AppClassLoader发起,但是AppClassLoader并不会尝试去加载该类,而是把这个任务委托给他的父类,即ExtClassLoader,而ExtClassLoader也不会去加载,而是又委托给他的父类,即BootStrap,BootStrap已经是终极大boss了,他不能委托给其他人,只好自己去寻找class文件,如果他找到了class文件,则将之加载,当他找不到时,又把任务推给儿子,也就是ExtClassLoader,ExtClassLoader这时才会去寻找,如果他找到了class文件,则将之加载,当他找不到时,又把任务推给儿子,也就是AppClassLoader,如果他找到了class文件,则将之加载,当他找不到时,则抛出一个ClassNotFoundException,加载请求的发起者不会再去寻找自己的儿子让他加载。

看下面一段代码,相关分析都在注释里:


    public static void main(String[] args) {
        // 先得到类加载器,再拿到类加载器的字节码,最后根据字节码拿到类加载器的名称
        System.out.println(ClassLoaderTest.class.getClassLoader().getClass()
                .getName());
        // System的类加载器为null,说明System的类加载器是BootStrap
        System.out.println(System.class.getClassLoader());
    }

输出:

说明目前运行类的类加载器是AppClassLoader,如果我们把当前类打包成一个jar包,放在C:\Program Files\Java\jre1.8.0_31\lib\ext目录下(每个人不一样),我们再尝试运行,看输出:

这次变成了ExtClassLoader来加载类了,为什么呢?稍微分析一下就会很清楚,首先是AppClassLoader发起一个加载类的请求,这个请求层层上传,一直传到他的爷爷也就是BootStrap那里,他的爷爷没找到class文件又把请求发回给ExtClassLoader,因为C:\Program Files\Java\jre1.8.0_31\lib\ext文件夹中已经有了我们要加载的类,而这个文件夹又恰好由ExtClassLoader来负责加载,所以ExtClassLoader就把这个类加载了,消息就不再往儿子那里传递了,所以输出的是ExtClassLoader加载了类。

通过下面的代码,我们可以看出类加载器之间的父子关系:

    @Test
    public void test2(){
        //拿到一个类加载器
        ClassLoader loader = ClassLoaderTest.class.getClassLoader();
        //循环依次遍历loader的父类
        while(loader!=null){
            System.out.println(loader.getClass().getName());
            loader = loader.getParent();
        }
        //最后打印出loader的老祖宗,null
        System.out.println(loader);
    }

输出:

时间: 2024-10-12 13:29:40

类加载器及其委托机制的深入分析的相关文章

44_类加载器及其委托机制的深入分析

什么是类加载器?------->加载类的工具 类加载器做了些什么事情?------>从硬盘把.class加载到内存,并做了一些处理,处理完成后得到的就是字节码. Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类: BootStrap.ExtClassLoader.AppClassLoader 类加载器也是Java类,因为其他是java类的加载器本身也要被类加载器加载,显然必须有一个类加载器不是java类,这就是BootStrap. BootStrap是

java类加载器及其委托机制

1.什么是类加载器,类加载器父子结构.BootStrap-->ExtClassLoader-->AppClassLoader,级别依次降低 2.类加载器之间的父子关系和管辖范围 3.类加载器的委托机制.当前加载器加载类,先通过上级加载器加载,若上级无法加载,只能当前加载器加载,不能由下级加载器加载

第十二章 类加载器和反射机制

12 类加载器和反射机制 12.1 类加载器 负责将.class文件加载到内存中,并为之生成对应的Class对象. 1.类的加载 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载.连接.初始化三个步骤来实现对这个类的初始化. 加载 就是指将calss文件读入到内存,并为之穿件一个Class对象. 任何类被使用时系统都会建立一个Class对象. 连接 验证    是否有正确的内部结构,并和其他类协调一致 准备    负责为类的静态成员分配内存,并设置默认初始化值 解析    将类

类加载的父亲委托机制

我们都知道.类加载器用来把类加载到java虚拟机.从JDK2.0开始,类的加载过程采用父亲委托机制.JVM的ClassLoader采用的是树形结构,除了根类加载器以外,每个ClassLoader都会有且仅有一个父类加载器,用户自定义的ClassLoader默认的父类加载器是系统类加载器,当然你可以自己指定需要用个ClassLoader的实例,我们来看他们的父子关系: 父类委托机制中,当一个java程序请求加载器loader1加载Hello类时,loader1首先委托自己的父亲加载器加载hello

java 类加载器   双亲委派机制

先上图,看一下加载器. 1.BootStrapClassLoader:启动类加载器,该ClassLoader是在启动时候创建的,是写在JVM内核里的,它不是一个字节码文件,是由c++编写的二进制代码,所以开发者无法获取到该启动类的引用,也就不能通过引用来进行操作.这个加载器是加载$JAVA_HOME/jre/lib下面的类库(或者通过参数-Xbootclasspath指定). 2.EXTClassLoader:扩展类加载器,ExtClassLoader会加载 $JAVA_HOME/jre/lib

类加载器-双亲委托

双亲委托(代理)模型:当类加载器收到加载类或资源的请求时,通常都是先委托给父类加载器加载,当父类加载器找不到指定类或资源时,会委托给始祖类加载器进行加载,始祖类加载器也找不到资源的话,自身才会执行实际的类加载过程.

类加载器的深入讲解与应用

第8单元:类加载器的深入讲解与应用 第8单元:类加载器的深入讲解与应用 第8单元:类加载器的深入讲解与应用 44.类加载器及其委托机制的深入分析 package java_5; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOExc

java高新技术-类加载器

1.类加载器及委托机制的深入分析 > 类加载器的作用:一个java文件中的出现的类,首先要把这个类的字节码加载到内存中,这个类的信息放在硬盘的classPath下的class文件中,  把class文件中的内容加载到内存中去,在进行一些处理,处理完的结果就是字节码,这一系列工作是类加载器在做. > Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:    BootStrap,ExtClassLoader, AppClassLoader > 类加载

Java类加载器的工作原理

Java类加载器的作用就是在运行时加载类.Java类加载器基于三个机制:委托.可见性和单一性.委托机制是指将加载一个类的请求交给父类加载 器,如果这个父类加载器不能够找到或者加载这个类,那么再加载它.可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类 加载器加载的类.单一性原理是指仅加载一个类一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类.正确理解类加载器能够帮你解决 NoClassDefFoundError和java.lang.ClassNo