Hello World

类加载器

1.  概述

  虚拟机把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,这个动作的代码模块称为类加载器。

2.  类与类加载器

  对于任意一个类,都需要加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性。

  比较两个是否相等只有在同一个类加载器的前提下才有意义,

  对于同一个class文件,如果他们的类加载器不同,那这两个类就必定不相等。

3.  类加载器

3.1 启动类加载器(Bootstrap ClassLoder)

  这个类负责将存放在<JAVA_HOME>\lib目录下,并且是虚拟机识别(仅按照文件名识别,如rt.jar,名字不符合的类库不会被加载)的类库加载到虚拟机内存中,启动类加载器无方法被Java程序直接引用。

3.2 扩展类加载器(Extension ClassLoder)

  该类加载器由 sun.misc.Launcher$ExtClassLoder 实现,负责加载<JAVA_HOME>\lib\ext目录下的,或者被 java.ext.dirs 系统变量所指定的所有类库,开发者可直接使用扩展类加载器。

3.3 应用程序类加载器(Application ClassLoder)

  该类加载器由 sun.misc.Launcher$AppClassLoder 实现,该类加载器是ClassLoder中getSystemClassLoder()的返回值,负责加载用户路径(ClassPath)下指定的类库一般情况下这个就是默认的类加载器。

3.4 自定义类加载器

  通过继承 ClassLoader ,然后重写findClass()方法自定义类加载器

4. 双亲委派模型

  

4.1 工作原理  

  如果有一个类加载器收到以一个类加载的请求,它先把这个请求委派给父类去完成,当父类无法完成这个加载请求时,子类才会尝试自己去加载这个类。

  Java 类随着它的类加载器一起具备了一种带有优先级的层次关系,保证Java体系中最基础的行为。

4.2 作用

  保证核心类库在内存中的唯一性。

  如果用户自定义了一个Object类,由于引导类加载器已经加载了这个类,则直接返回已经加载的类,而不会继续加载这个类。

  

public class String {

    public static void main(String[] args) {
        System.out.println(123);
    }
}

  自定义一个String类,并编写main方法,运行后报错如下:

  

 

   虚拟机加载的是jdk自带的String类,然而String 类没有main方法,所以报错。

5. 破坏双亲委派模型

  1. JDK在1.2之后引入双亲委派模型,为了向前兼容,java.lang;ClassLoder添加了一个protected 的 findClass(), 用于实现自定义的类加载

  2. Java提供的一些服务需要调用第三方的代码,引入线程上下文类加载器(Thread Context ClassLoder)。该类加载器通过 java.lang.Thread 类的 setContextClassLoader() 进行设置。默认为应用程序类加载器。

  该过程中父类加载器请求子类加载器完成类加载请求。

  Java中定义了java.sql.Driver接口,但是其实现是由各个厂商来实现,Driver接口是在rt.jar中,本来应该有引导类加载器加载,实际上是通过线程上下文类加载器来加载其具体实现的。

 

posted @ 2018-09-08 18:48  小小忧愁米粒大  阅读(148)  评论(0编辑  收藏  举报
瞅啥瞅,好好看书