Java体系中定义了3中类加载器,分别如下:
- Bootstrap ClassLoader(引导类加载器).负责加载下述3中情况下所制定的核心类库:
- %JAVA_HOME%/jre/lib目录
- -Xbootclasspath 参数所指定的目录
- 系统属性sun.boot.class.path指定的目录中特定名称的jar包
- Extension ClassLoader(扩展类加载器) 加载扩展类,拓展JVM的类库
- %JAVA_HOME%/jre/lib/ext目录
- 系统属性java.ext.dirs所指定的目录中的所有类库
- System ClassLoader(系统类加载器) 加载Java应用程序类库,加载类库的路径由系统环境变量ClassPath、-cp或系统属性java.class.path指定
-
图中各类加载器之间的关系,并非Java类面向对象的三大特性之一的那种“继承”关系。毕竟引导类加载器是使用C++语言编写而成的,Java类编写的类加载器想去继承也无法继承。
- 图中所表达的关系,仅仅是类的委托加载机制,尤其是著名的“双亲委派”。虽然几种加载器之间没有继承关系,但是扩展类加载器及用户自定义加载器,却都继承自java.lang.ClassLoader这个基类。
- 图中所表达的委托关系,本质上通过java.lang.ClassLoader.parent字段实现,该字段表示父加载器。对于引导类加载器,并没有所谓的父加载器的概念,因为引导类加载器本身是随JVM的启动而初始化,并且该类中的字段和方法全部是静态字段和方法,并不需要实例化便能使用。而除了引导类加载器之外的所有类加载器,由于都继承自java.lang.ClassLoader这个基类,因此便都有parent字段,由于该字段被final private 修饰,因此子类只能通过调用java.lang.ClassLoader的构造函数才能初始化该字段。对于扩展类加载器和系统类加载器,在JVM第一次加载Java类时会被创建,并完成其父类加载器的设定。扩展类加载器与系统类加载器在sun.misc.Launcher类的构造函数中完成初始化,sun.misc.Launcher类的构造函数逻辑如下:
-
public class Launcher { private static URLStreamHandlerFactory factory =new Factoru(); private static Launcher launcher = new Launcher();//启动器 private static String bootClassPath = System.getProperty("sun.boot.class.path");//引导类加载器路径 private ClassLoader loader;//系统类加载器 public Launcher() { ClassLoader extc1; //创建扩展类加载器 extc1 = sun.misc.Launcher.ExtClassLoader.getExtClassLoader(); //创建系统类加载器 loader = sun.misc.Launcher.AppClassLoader.getAppClassLoader(extc1); } }
- @未完待续。。。。。。