双亲委派模型
概念:加载类的时候,⾸先会把该请求委派该⽗类加载器的 loadClass() 处理,因此所有的
请求最终都应该传送到顶层的启动类加载器 BootstrapClassLoader 中。当⽗类加载器⽆法处理
时,才由⾃⼰来处理。(从下往上,从上往下)
代码:
public class ClassLoaderDemo {
public static void main(String[] args) {
System.out.println("ClassLodarDemo's ClassLoader is " +ClassLoaderDemo.class.getClassLoader());
System.out.println("The Parent of ClassLodarDemo's ClassLoaderis " + ClassLoaderDemo.class.getClassLoader().getParent());
System.out.println("The GrandParent of ClassLodarDemo'sClassLoader is " +ClassLoaderDemo.class.getClassLoader().getParent().getParent());
}
}
输出:
ClassLodarDemo's ClassLoader is
sun.misc.Launcher$AppClassLoader@18b4aac2
The Parent of ClassLodarDemo's ClassLoader is
sun.misc.Launcher$ExtClassLoader@1b6d3586
The GrandParent of ClassLodarDemo's ClassLoader is null
解释为什么调用不到最顶层,是因为使用C写的。
双亲委派模型优点:双亲委派模型保证了Java程序的稳定运⾏,可以避免类的重复加载(JVM 区分不同类的⽅式不仅仅根据类名,相同的类⽂件被不同的类加载器加载产⽣的是两个不同的类),也保证了 Java 的核⼼ API 不被篡改。如果不⽤没有使⽤双亲委派模型,⽽是每个类加载器加载⾃⼰的话就会出现⼀些问题,⽐如我们编写⼀个称为 java.lang.Object 类的话,那么程序运⾏的时候,系统就会出现多个不同的Object 类。
自己的理解(二话不说上代码):运行会报找不到main方法。因为首先是加载的根的String方法。
package lang;
public class String {
public String toString(){
return "hello";
}
public static void main(String[] args){
String s = new String();
s.toString();
}
}
如果我们不想⽤双亲委派模型怎么办?
为了避免双亲委托机制,我们可以⾃⼰定义⼀个类加载器,然后重载 loadClass() 即可。
如何⾃定义类加载器?
除了 BootstrapClassLoader 其他类加载器均由 Java 实现且全部继承⾃
java.lang.ClassLoader 。如果我们要⾃定义⾃⼰的类加载器,很明显需要继承 ClassLoader 。
参考:JavaGuide等