双亲委派模型工作原理
如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即ClassNotFoundException),子加载器才会尝试自己去加载。
双亲委派模型经典案例
package java.lang;
public class String {
public static void main(String[] args) {
System.out.println("hello world!");
}
}
执行这个main方法,大家觉得能正常输出hello world! 吗?
运行main方法后:
java.lang.NoSuchMethodError: main
Exception in thread "main"
原因分析:
- 运行这段代码,JVM会首先创建一个自定义类加载器,不妨叫做AppClassLoader,并把这个加载器链接到委托链中:AppClassLoader -> ExtClassLoader -> BootstrapLoader。
- 然后AppClassLoader会将加载java.lang.String的请求委托给ExtClassLoader,而 ExtClassLoader又会委托给最后的启动类加载器BootstrapLoader。
- 启动类加载器BootstrapLoader只能加载JAVA_HOME\jre\lib中的class类(即J2SE API),问题是标准API中确实有一个java.lang.String(注意,这个类和我们自定义的类是完全两个类)。 BootstrapLoader以为找到了这个类,毫不犹豫的加载了j2se api中的java.lang.String。
- 最后出现上面的加载错误(注意不是异常,是错误,JVM退出),因为API中的String类是没有main方法的。
结论:我们当然可以自定义一个和API完全一样的类,但是由于双亲委托模型,使得我们不可能加载上我们自定义的这样一个类。所以J2SE规范中希望我们自定义的包有自己唯一的特色。还有一点,这种加载器原理使得JVM更加安全的运行程序,因为黑客很难随意的替代掉API中的代码。
网友评论