zoukankan      html  css  js  c++  java
  • 加载器三:类加载器工作步骤

    什么是类加载器

    类加载器负责所有类的加载,系统为所有被载入内存的类生成一个java.lang.Class实例。一旦一个类被载入到JVM中,同一个类就不会被再次载入。但是如何判断“同一个类”呢?

    正如一个对象有唯一标示一样,一个被载入JVM的类也拥有唯一的标示。在Java中一个类用其全限定名(包名+类名)作为标示;但是在JVM中,一个类用其全限定名和类加载器作为唯一标示,也就是说两个类加载器加载的同名类是不同的

    当JVM启动时,会形成由三个类加载器组成的初始类加载器层次结构:

    Bootstrap ClassLoader:根加载器

    Extension ClassLoader:扩展类加载器

    System ClassLoader:系统类加载器

    Bootstrap ClassLoader

    引导(也称为原始或根)类加载器,它负责加载Java的核心类。在Sun的JVM中,当执行java.exe命令是,使用Xbootclasspath选项或使用-D选项指定sun.boot.class.path系统属性值可以指定加载附加的类

    根类加载器肥城特殊,它并不是java.lang.ClassLoader的子类,而是有JVM自身实现的。

    Extension ClassLoader

    扩展类加载器,负责加载JRE的扩展目录(%JAVA_HOME%jrelibext或者有java.ext.dirs系统属性指定的目录)中JAR包的类。

    通过这种方式,就可以为JAva扩展核心类以外的新功能面只要把自己开发的类打包成JAR文件,然后放入JAVA_HOMEjrelibext路径即可。

    System ClassLoader

    系统(应用)类加载器,它负责在JVM启动是加载 来自java命令的-classpath选项、java.class.path系统属性,或CLASSPATH环境变量所指定的JAR包和类路径。程序可以通过ClassLoader的静态方法getSystemClassLoader()来获得系统类加载器。如果没有特别指定 ,则用户自定义的类加载器都以其作为父加载器。

    类加载器机制

    JVM的类加载机制主要与三种:

    全盘负责:就是当一个类加载器负责加载某个Class时,该Class所以来的和引用的其他Class也将有该类加载器负责加载,除非明确指出使用另一个类加载器来加载
    父类委托:先让parent(父)类加载器加载该Class,只有在父类加载器无法加载该类时才会尝试自己加载该类。
    缓存机制:会保证所有加载过的Class都会被缓存,当程序需要是由牧歌 Class时,类加载器先从缓存区搜索该Class,只有当缓存区中不存在该Class对象时,系统 才会读取该类对应的二进制数据,并将其转换Class对象,存入缓存区中。这就是为什么修改了Class后,必须重新启动JVM,程序所做的修改才会生效的原因
    类加载器之间的父子关系并不一定是继承上的父子关系,也有可能是包装关系,这里的父子关系时类加载器实例之间的关系

    JVM的跟类加载器并不是Java实现的,而且由于程序通常无需访问根类加载器,因此使用扩展类加载器访问父类加载会返回null。但是实际上,扩展类加载器的父类加载器是根类加载器 

    // 获取系统类加载器的父类加载器:得到扩展类加载器
            ClassLoader extensionLader = systemLoader.getParent();
    System.out.println("扩展类加载器:" + extensionLader);
    System.out.println("扩展类加载器的加载路径:"
                + System.getProperty("java.ext.dirs"));
    System.out.println("扩展类加载器的parent: "
                + extensionLader.getParent());// 返回null
    View Code

    类加载器加载Class大致要8个步骤:

    1:检测此Class是否载入过(即缓存区中是够有此Class),如果有则进入第8步,否则继续执行第2步。
    2:如果父类加载器不存在(如果没有父类加载器,则,要么paret一定是根类加载器,要么本身就是根类加载器),则跳到第4步执行;否则,接着执行第3步。
    3:请求使用父类加载器去加载目标类,如果成功载入则跳到第8步,否则跳到第5步执行。
    4:请求使用根类加载器加载目标类,如果成功加载则跳到第8步,否则跳到第7步。
    5:当前类加载器尝试寻找Class文件(从与此ClassLoader想过的类路径中寻找),如果找到则执行第6步,否则,跳到第7步。
    6:从文件中载入Class,成功加载后跳到第8步。
    7:抛出ClassNotFoundException异常。
    8:返回对应的java.lang.Class对象。

    其中,第5、6允许重写ClassLoader的findClass()方法来实现自己的载入策略,深知重写loadClass()方法来实现自己的载入过程。

    加载步骤如图所示(请放大网页查看[Ctrl+滚轮]):

  • 相关阅读:
    2018.5.5-6 GDCPC2018广东省赛 6/10 Rank12 Au
    网络流24题总结
    BZOJ4259 残缺的字符串 FFT
    [转]CodePlus 2018 3月赛 博弈论与概率统计
    Aiiage Camp Day6 J Sort
    Daily Scrum7
    Daily Scrum6
    Daily Scrum5
    Daily Scrum4
    Daily Scrum3
  • 原文地址:https://www.cnblogs.com/fuluS/p/4704894.html
Copyright © 2011-2022 走看看