jdk1.2后 虚拟机 的类加载器 使用的就是双亲委派模型;
主要有三种加载器:
1:Bootstrap classloader--启动类加载器,也叫根类加载器,它负责加载Java的核心类库,加载如(%JAVA_HOME%/lib)目录下,C++写的;
2:extension classloader --扩展类加载器:它负责加载扩展目录(%JAVA_HOME%/jre/lib/ext)下的jar包
3:app classloader -- 应用程序加载器:是加载CLASSPATH环境变量所指定的jar包与类路径;
各种类加载器间关系:以组合关系复用父类加载器的父子关系,注意,这里的父子关系并不是以继承关系实现的。
Bootstrap,这个加载器很特殊,它不是Java类,因此它不需要被别人加载,它嵌套在Java虚拟机内核里面,也就是JVM启动的时候Bootstrap就已经启动,它是用C++写的二进制代码.这也是我们在测试时为什么发现System.class.getClassLoader()结果为null的原因,这并不表示System这个类没有类加载器,而是它的加载器比较特殊,是BootstrapClassLoader,由于它不是Java类,因此获得它的引用肯定返回null。
双亲模型保证了:无论哪个类加载器要加载这个方法,最终都要委派给模型最顶端的启动类加载器进行加载。保证了java程序的稳定性,比如你永远无法加载一个重名为object的类;
注:解释自定义一个加载器,强行用defindClass()加载一个以“java.lang"开头的类也不会成功,虚拟机会抛出异常;
如果用户自己写了一个名为java.lang.Object的类,并放在程序的Classpath中,那系统中将会出现多个不同的Object类,java类型体系中最基础的行为也无法保证,应用程序也会变得一片混乱。
委托机制的意义 — 防止内存中出现多份同样的字节码
比如两个类A和类B都要加载System类:
如果不用委托而是自己加载自己的,那么类A就会加载一份System字节码,然后类B又会加载一份System字节码,这样内存中就出现了两份System字节码。
如果使用委托机制,会递归的向父类查找,也就是首选用Bootstrap尝试加载,如果找不到再向下。这里的System就能在Bootstrap中找到然后加载,如果此时类B也要加载System,也从Bootstrap开始,此时Bootstrap发现已经加载过了System那么直接返回内存中的System即可而不需要重新加载,这样内存中就只有一份System的字节码了。