BootStrap ClassLoader(引导类加载器):
引导类加载器是有c/c++编写成的,没有继承于ClassLoader类, 负责加载 JAVA_HOMElib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被虚拟机认可(按文件名识别,如 rt.jar)的类,例如java包下的,javax包下的类就需要引导类加载器进行加载。
Extension ClassLoader(扩展类加载器):
由java编写成的类加载器,继承于ClassLoader类,负责加载 JAVA_HOMElibext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类库。根类加载器从系统属性sun.boot.class.path所指定的目录中加载类库。默认为jre目录下的lib目录下的class文件,该加载器没有父加载器。负责加载虚拟机的核心类库,如java.lang.*。Object类就是由根类加载器加载的。
Application ClassLoader(系统类加载器):
负责加载用户路径(classpath)上的类库。JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承 java.lang.ClassLoader实现自定义的类加载器。像新导入的jar包中的类,就由该加载器进行加载。
当一个加载类接收到加载请求时,他首先检查缓存中有没有已经加载好的类,如果有就直接拿出来,没有的话他首先不会自己加载,而是把加载的任务委托给父类加载器,一直向上委托,直到父类加载器为null,那么此时根加载器就会尝试加载类(从java,javax包下查找),如果完成了加载,那么就返回加载的对象,如果没有那么就交给子类加载。假设我们加载类就需要系统类加载器去加载,那么父类就自然而然的检查不到,最后子类不得不自己加载。
双亲委派机制优点:保证了底层API的安全性,例如假设我们需要调用java.lang.String相关api,那么系统就会由BootStrap Classloader去加载该类。当某个人修改了部署在服务器中的项目,自己在src下添加了一个java.lang.String类,那么系统不会先使用系统加载器去加载该类,而是使用引导类加载器去加载该地址的类文件。一定程度上防止了底层类API被改写覆盖。同时可以防止重复加载。继续上面的例子,当父类的String被加载了,那么后面的假的String就不会被加载。



