【JVM】双亲委派模型、优势及如何破坏双亲委派模型

一、基本概念

一个类是由加载它的类加载器和这个类本身来共同确定其在Java虚拟机中的唯一性。

二、什么是双亲委派模型

双亲委派模型
类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
双亲委派模型要求除了最顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器,在双亲委派模型中是采用组合关系来复用父类加载器的相关代码的。

三、双亲委派模型的实现

双亲委派模型实现的源码如下:

protected synchronized Class<?> loadClass(String name,boolean resolve)throws ClassNotFoundException{
    //check the class has been loaded or not
    Class c = findLoadedClass(name);
    if(c == null){
        try{
            if(parent != null){
                c = parent.loadClass(name,false);
            }else{
                c = findBootstrapClassOrNull(name);
            }
        }catch(ClassNotFoundException e){
            //if throws the exception ,the father can not complete the load
        }
        if(c == null){
            c = findClass(name);
        }
    }
    if(resolve){
        resolveClass(c);
    }
    return c;
}

由源码可知,双亲委派模型的实现是在java.lang.ClassLoader类的loadClass()方法中。
类加载时,JVM会首先检查当前是否已经被加载过该类,如果没有加载且父加载器非空则会调用父类加载器的loadClass()方法,否则默认使用启动类加载器作为父加载器。如果父加载器无法完成加载(抛出ClassNotFoundException异常)则调用自己的findClass()方法进行加载。

四、双亲委派模型的优势

1、避免类的重复加载

每次进行类加载时,都尽可能由顶层的加载器进行加载,保证父类加载器已经加载过的类,不会被子类再加载一次,同一个类都由同一个类加载器进行加载,避免了类的重复加载。

2、防止系统类被恶意修改

通过双亲委派模型机制,能保证系统类由Bootstrap ClassLoader进行加载,用户即使定义了与系统类相同的类,也不会进行加载,保证了安全性。

五、如何破坏双亲委派模型

某些情况下,需要由子类加载器去加载class文件,这时就需要破坏双亲委派模型。要破坏双亲委派模型,可以通过重写ClassLoader类的loadClass()方法实现。
由于Java中所有类都默认继承Object类,但由于JDK的保护机制,系统类不能由自定义类加载器完成加载,需要对加载的类做判断,如果类名是java开头,则由拓展类加载器或引导类加载器进行加载。
典型的打破双亲委派模型的例子有Tomcat与OSGI,这部分需要详细了解可以参考源码。

原创文章 10 获赞 10 访问量 4762

猜你喜欢

转载自blog.csdn.net/Steven_L_/article/details/105820947
今日推荐