天天看點

類加載器和雙親委派模型

類加載器

JVM提供了三種類加載器:啟動類加載器、擴充類加載器、應用程式類加載器。他們所加載的内容如下:

  • 啟動類加載器:加載JAVA_HOME/lib下面的jar;
  • 擴充類加載器:加載JAVA_HOME/lib/ext下面的jar;
  • 應用程式類加載器:加載使用者路徑下的jar,比如我們自己寫的代碼,會加載classpath路徑下的類;

    除了上述三種方式,我們可以繼承ClassLoad類來自定義自己的類加載器。

雙親委派模型

雙親委派模型:當一個類加載器收到類加載請求的時候,不會自己去加載這個類,而是向上請求自己的父加載器去加載這個類,父加載器也會繼續向上請求它的父加載器去加載這個類,直到根類加載器,即啟動類加載器,如果啟動類加載器中找不到這個類,則依次向下請求其子類加載器去加載這個類,即擴充類加載器加載這個類,如果擴充類加載器也沒有這個類,則繼續向下請求,如果應用程式類加載器還沒有找到這個類,則交給自定義加載器來完成,如果最後自定義加載器也沒有,則抛出ClassNotFound異常。

類加載器和雙親委派模型

雙親委派模型的好處是能保證加載類的唯一性和安全性,比如你重寫了一個String類,那麼由于JVM已經存在了String類,是以最後加載的時候由于會不斷地向上請求父類加載器,而父加載器是已經存在String類的,是以你定義的String類便不會加載。

源碼如下:

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{
        //	如果父類加載器不是null
            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()方法來打破這個模型

繼續閱讀