类加载器最初是由java Applet需求而开发出来的,现在java Applet技术基本死掉。但是类加载器却在类的层次划分,OSGi,热部署,代码加密等领域大放异彩。
类加载器不只是把类加载在虚拟机中,对于任意一个类,都需要类加载器和类本身决定其在Java虚拟机中的唯一性。每一个类加载器都拥有独立的类名称空间。
比如两个类是否相等要在这两个类被同一个类加载器加载的前提下才有意义。否则,即使两个类来自同一个class文件,被不同的类加载器加载,那么这两个类也是不同的。
从虚拟机的角度看,类加载器包括两种。一种是启动类加载器:是虚拟机的一部分,使用C++实现。另一种就是所有其他的类加载器,由Java实现,独立于虚拟机外部。这类的加载器都继承抽象类java.lang.ClassLoader
1.启动类加载器(Bootstrap ClassLoader)
启动类加载器主要负责将<JAVA_HOME>\lib目录中或者被-XbootClasspath设置的类库加载到虚拟机内存中。启动类加载器不能被Java程序直接调用。
2.扩展类加载器(Extension ClassLoader)
扩展类加载器负责将<JAVA_HOME>\lib\ext目录中,或者被java.ext.dirs设定的目录中的类库加载到虚拟机内存。开发者可以调用扩展类加载器。
3.应用程序类加载器(Application ClassLoader)
负责加载用户路径上指定的类库。开发者可以直接使用。
双亲委派
双亲委派模型要求除了顶层的启动类加载器以外,其余加载器必须有自己的父类加载器。
双亲委派的工作过程是:
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类。而把这个请求委派给父类加载器去完成。每一个层次的类加载器都是如此。因此所有加载请求最终都应该传送到顶层的启动类加载器中,只有当父类加载器反馈无法完成这个加载请求时,子类才会尝试去自己加载。
双亲委派模型的好处:
双亲委派模型对Java程序的稳定有很重要的作用。Java类随着类加载器具备了带有优先级的层次关系,例如类java.lang.Object,它存放在rt.jar包中,无论哪个类加载器要加载这个类,都要委派给最顶端的启动类加载器加载。因此Object类在程序的各个加载器环境中都是同一个类。