JVM双亲委托模型

jvm.jpg

双亲委派模型工作原理

如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即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"

原因分析:

  1. 运行这段代码,JVM会首先创建一个自定义类加载器,不妨叫做AppClassLoader,并把这个加载器链接到委托链中:AppClassLoader -> ExtClassLoader -> BootstrapLoader。
  2. 然后AppClassLoader会将加载java.lang.String的请求委托给ExtClassLoader,而 ExtClassLoader又会委托给最后的启动类加载器BootstrapLoader。
  3. 启动类加载器BootstrapLoader只能加载JAVA_HOME\jre\lib中的class类(即J2SE API),问题是标准API中确实有一个java.lang.String(注意,这个类和我们自定义的类是完全两个类)。 BootstrapLoader以为找到了这个类,毫不犹豫的加载了j2se api中的java.lang.String。
  4. 最后出现上面的加载错误(注意不是异常,是错误,JVM退出),因为API中的String类是没有main方法的。

结论:我们当然可以自定义一个和API完全一样的类,但是由于双亲委托模型,使得我们不可能加载上我们自定义的这样一个类。所以J2SE规范中希望我们自定义的包有自己唯一的特色。还有一点,这种加载器原理使得JVM更加安全的运行程序,因为黑客很难随意的替代掉API中的代码。

你可能感兴趣的:(JVM双亲委托模型)