课程咨询 :0731-88220680

长沙Java培训 > 达内新闻 > 长沙java培训分享:Java类加载器
  • 长沙java培训分享:Java类加载器

    发布:长沙Java培训      来源:达内新闻      时间:2016-01-15


  • 长沙java培训带小伙伴首先回顾一下,java虚拟机载入java类的步骤:java文件经过编译器编译后变成字节码文件(.class文件),类加载器(ClassLoader)读取.

    class文件,并且转换成java.lang.Class的一个实例,最后通过newInstance方法创建该类的一个对象。ClassLoader的作用就是根据一个类名,找到对应的字节码,根据这些字节码定义出对应的类,该类就是java.lang.Class的一个实例。

    类加载器的组织结构

    长沙java培训

    java有三个初始类加载器,当java虚拟机启动时,它们会按照以下顺序启动:Bootstrap classloader -> extension classloader -> system classloader。三者的关系:bootstrap classloaderextension classloaderparentextension classloadersystem classloaderparent

    bootstrap classloader

    它是最原始的类加载器,并不是由java代码写的,是由原生代码编写的。Java有一次编译、所有平台运行的效果,就是因为它写了一份功能相同,但针对不同平台不同语言实现的底层代码。它负责加载java核心库,大家可运行以下代码,看看自己本地的java核心库在哪里:

    URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();

    for (int i = 0; i < urls.length; i++) {

      System.out.println(urls[i].toExternalForm());

    }

    本人的运行结果:

    file:/home/eric/jdk1.6.0_35/jre/lib/resources.jar

    file:/home/eric/jdk1.6.0_35/jre/lib/rt.jar

    file:/home/eric/jdk1.6.0_35/jre/lib/sunrsasign.jar

    file:/home/eric/jdk1.6.0_35/jre/lib/jsse.jar

    file:/home/eric/jdk1.6.0_35/jre/lib/jce.jar

    file:/home/eric/jdk1.6.0_35/jre/lib/charsets.jar

    file:/home/eric/jdk1.6.0_35/jre/lib/modules/jdk.boot.jar

    file:/home/eric/jdk1.6.0_35/jre/classes

    extension classloader

    它用来加载JRE的扩展目录(JAVA_HOME/jre/lib/extjava.ext.dirs系统属性指定的)JAR的类包。注意,因为它是bootstrap classloader加载的,所以当你运行:

    ClassLoader extensionClassloader=ClassLoader.getSystemClassLoader().getParent();

    System.out.println("the parent of extension classloader : "+extensionClassloader.getParent());

    输出的是:the parent of extension classloader : null

    system classloader

    它用于加载classpath目录下的jar包,我们写的java类,一般都是由它加载,除非你自己制定个人的类加载器。

    长沙java培训分享:全盘负责委托机制

    classloader加载类时,使用全盘负责委托机制,可以分开两部分理解:全盘负责,委托。

    全盘负责机制:若类A调用了类B,则类B和类B所引入的所有jar包,都由类A的类加载器统一加载。

    委托机制:类加载器在加载类A时,会优先让父加载器加载,当父加载器加载不到,再找父父加载器,一直找到bootstrap  classloader都找不到,才自己去相关的路径去寻找加载。以下是ClassLoader的源码:

    protected synchronized Class<?> loadClass(String name, boolean resolve)

      throws ClassNotFoundException

        {

      // First, check if the class has already been loaded

      Class c = findLoadedClass(name);

      if (c == null) {

          try {

        if (parent != null) {

            //从父加载器加载

            c = parent.loadClass(name, false);

        } else {

            //bootstrap loader加载

            c = findBootstrapClassOrNull(name);

        }

          } catch (ClassNotFoundException e) {

                    // ClassNotFoundException thrown if class not found

                    // from the non-null parent class loader

                }

                if (c == null) {

              // If still not found, then invoke findClass in order

              // to find the class.

              c = findClass(name);

          }

      }

      if (resolve) {

          resolveClass(c);

      }

      return c;

        }

    长沙java培训举个例子,类加载器加载类A的过程:

    1、判断是否已经加载过,在cache里面查找,若有,跳7;否则下一步

    2、判断当前加载器是否有父加载器,若无,则当前为ext classloader,跳去4;否则下一步

    3、请求父加载器加载该类,若加载成功,跳7;若不成功,即父加载器不能找到该类,跳2

    4、请求jvmbootstrap classloader加载,若加载成功,跳7;若失败,跳5

    5、当前加载器自己加载,若成功,跳7;否则,跳6

    6、抛出ClassNotFoundException

    7、返回Class

    编写自己的类加载器

    Java加载类的过程,实质上是调用loadClass()方法,loadClass中调用findLoadedClass()方法来检查该类是否已经被加载过,如果没有就会调用父加载器的loadClass(),如果父加载器无法加载该类,就调用findClass()来查找该类。

    所以我们要做的就是新建MyClassLoader继承java.lang.ClassLoader,重写其中的findClass()方法。主要是重新设计查找字节码文件的方案,然后调用definedClass来返回。

    当知识点一旦过多的时候小伙伴们,总觉得难以接受,长沙java培训机构希望看不到的小伙伴及时向我们的带班项目经理询问。

上一篇:八大高薪IT岗位!

下一篇:1万小时编程,你能体会到什么?

最新开班日期  |  更多

Java--零基础全日制班

Java--零基础全日制班

开班日期:01/20

Java--零基础业余班

Java--零基础业余班

开班日期:01/20

Java--大数据全日制班

Java--大数据全日制班

开班日期:01/20

Java--大数据业余制班

Java--大数据业余制班

开班日期:01/20

  • 网址:http://cs.java.tedu.cn     地址:长沙市开福区芙蓉中路一段 476 号建鸿达现代城 9 楼
  • 课程培训电话:0731-88220680     全国服务监督电话:400-827-0010
  • 服务邮箱 ts@tedu.cn
  • 2001-2016 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56