厦门Java培训
达内上海中山公园中心

13429669395

热门课程

达内:Java类加载器详解

  • 时间:2016-01-14
  • 发布:厦门Java培训
  • 来源:51cto


    首先,厦门达内java培训专家介绍一下java虚拟机载入java类的步骤:java文件经过编译器编译后变成字节码文件(.class文件),类加载器 (ClassLoader)读取.class文件,并且转换成java.lang.Class的一个实例,最后通过newInstance方法创建该类的 一个对象。ClassLoader的作用就是根据一个类名,找到对应的字节码,根据这些字节码定义出对应的类,该类就是java.lang.Class的 一个实例。

    1、类加载器的组织结构

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

    2、bootstrap classloader

    它是最原始的类加载器,并不是由java代码写的,是由原生代码编写的。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/ext或java.ext.dirs系统属性指定的)JAR的类包。达内java培训专家提示,它是bootstrap classloader加载的,所以当你运行:

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

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

    3、system classloader

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

    4、全盘负责委托机制

    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; 
    } 

    举个例子,类加载器加载类A的过程:

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

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

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

    (4)请求jvm的bootstrap classloader加载,若加载成功,跳7;若失败,跳5

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

    (6)抛出ClassNotFoundException

    (7)返回Class

    5、编写自己的类加载器

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

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

    以上就是厦门达内java培训专家讲解的java类加载器知识了。







原文链接:http://developer.51cto.com/art/201601/503984.htm
上一篇:达内浅析Java对象的深复制和浅复制
下一篇:达内:Java开发的8款实用的IDEA插件

达内教育蝉联荣登“2016百度数字资产榜单”职业教育类第一名

795万高校毕业生创历史新高,2017届毕业生就业近况几何?

恭喜达内获得《产学合作协同育人项目合作伙伴奖》

达内Java大数据捷报频传,最高薪资15000元

选择城市和中心
贵州省

广西省

海南省