zoukankan      html  css  js  c++  java
  • 类加载器及其双亲委托机制

    类加载器分为4种:

    1.根类(Bootstrap)加载器

    启动类加载器主要加载的是JVM自身需要的类,这个类加载使用C++语言实现的,不开源,是虚拟机自身的一部分,它负责将 <JAVA_HOME>/lib路径下的核心类库或-Xbootclasspath参数指定的路径下的jar包加载到内存中

    2.扩展类(Extension)加载器

    扩展类加载器是指Sun公司(已被Oracle收购)实现的sun.misc.Launcher$ExtClassLoader类,由Java语言实现的,是Launcher的静态内部类,它负责加载<JAVA_HOME>/lib/ext目录下或者由系统变量-Djava.ext.dir指定位路径中的类库

    扩展类加载器加载类是加载以jar包形式存在的class的,单独的class文件不加载

    3.应用类/系统类(System)加载器

    也称应用程序加载器是指 Sun公司实现的sun.misc.Launcher$AppClassLoader。它负责加载系统类路径java -classpath或-D java.class.path 指定路径下的类库,也就是我们经常用到的classpath路径,开发者可以直接使用系统类加载器,一般情况下该类加载是程序中默认的类加载器,通过ClassLoader#getSystemClassLoader()方法可以获取到该类加载器。

    4.自定义类加载器。


    双亲委托机制



    如上图所示,如果要加载Sample类,加载过程为:

    1.向自定义类加载器loader1发起申请加载,loader1委托给系统类加载器,系统类加载器委托给扩展类加载器,扩展类加载器委托给根类加载器

    2.根类加载器加载失败,返回给扩展类加载器;

    3.扩展类加载器加载失败,返回给系统类加载器

    4.系统类加载成功,返回给loader1


    举例说明:

    1.如java.lang.String等jdk自带的类,他们的类加载器是Bootstrap加载器

    2.引入外部jar包的类/非核心的jdk类,他们的类加载器是扩展类(Extension)加载器

    3.我们业务自定义的类,类加载器是应用类/系统类(System)加载器

    注意的一点,jvm提供了方法改变默认的系统类加载器,用户可以通过修改property:java.system.class.loader这个配置改变默认的系统类加载器

    4.数组类型的加载是在jvm运行期动态进行的,数组类型的加载器跟里面元素的加载器一致,如String[]的加载器是Bootstrap加载器,业务自定义类数组的加载器是应用类/系统类(System)加载器。如果数组的类型是原生类型,则此数组类没有加载器(注意:数组类型加载不是类加载器完成的,是jvm运行时动态加载的)



    ps:

    父加载器加载的类不能使用子加载器加载的类的任何信息,子加载器加载的类可以使用父加载器的内容

    例如:我们可以在我们自定义的类里使用String类,但是不能在String类里使用我们自定义的类


    如果一个类A里面要加载类B(例如在类A创建类B的实例),会使用加载类A的加载器来加载类B(但是还是会使用双亲委托机制)


    类加载器双亲委托模型的好处:

    1.可以确保java核心库的类型安全:所有的java应用都至少会引用java.lang.Object类,也就是说,java.lang.Object这个类会被加载到JVM中,如果这个加载过程是由JAVA应用自己的类加载器加载的,那么就可能会在JVM中存在多个版本的java.lang.Object这个类,而且这些类之间,是不兼容的,是互不可见的(正是命名空间在发挥作用 )

    借助于双亲委托机制,java的核心类库都是由根类加载器来加载完成,从而确保了java应用所使用的都是同一个版本的java核心类库,他们是互相兼容的

    2.可以确保java核心类库所提供的类不会被自定义的类所替换

    3.不同的类加载器可以为相同名称(binary name)的类创建额外的命名空间,相同名称的类可以并存在jvm中,只需要用不同的类加载器来加载它们即可,不同类加载器所加载的类之间是不兼容的,这就相当于在jvm内部创建了又一个相互隔离类空间,这类技术在很多框架中都得到了实际的应用


    在运行期,一个java类是由该类的完全限定名(binary name,二进制名)和用于加载该类的定义类加载器(defining loader)所共同决定的

    如果同样名字的类(即由相同的完全限定名)是由两个不同的加载器加载的,那么这些类是不同的,即便是.class文件完全一样,并且也是从相同的地方加载,亦如此


    当前类加载器(Current Classloader):

    每个类都会使用自己的类加载器(即加载自身的类加载器)来去加载其他的类(指的是所依赖的类)

    如果ClassX引用了ClassY,那么ClassX的类加载器,就会尝试加载ClassY(前提是ClassY没被加载的情况下)


  • 相关阅读:
    从客户端(&)中检测到有潜在危险的 Request.Path 值。
    对访问修饰关键字public, protected, internal and private的说明
    C#综合揭秘——细说多线程(下)
    iis下配置:php+mysql
    工厂模式(Factory Patter)
    HDU 1040 As Easy As A+B [补]
    HDU 1020 Encoding
    HDU 1076 An Easy Task
    UVA 100 The 3n + 1 problem
    民大OJ 1668 追杀系列第二发
  • 原文地址:https://www.cnblogs.com/billmiao/p/9872213.html
Copyright © 2011-2022 走看看