ClassLoader的雙親委派模型

類加載器用以實現類加載功能,而且肯定被加載的類在Java虛擬機中的惟一性。java

注意:由同一個類加載器加載,則這兩個類相等,由不一樣的類加載器加載,則這兩個類不相等。bash

咱們知道類加載器主要分爲:ide

  • 啓動類加載器
  • 擴展類加載器
  • 應用程序類加載器

啓動類加載器

負責加載如下類:ui

  • 存放在JAVA_HOME\lib目錄中的類;
  • 被-Xbootclasspath參數所指定路徑中、而且是被虛擬機識別的類庫。

注意:啓動類加載器不能直接被java程序直接飲用。spa

擴展類加載器

負責加載如下類:code

  • JAVA_HOME\lib\ext目錄中的類;
  • 被java.ext.dirs系統變量所指定的路徑中的全部類。

注意:開發者能夠直接使用擴展類加載器。cdn

應用程序類加載器

負責加載用戶類路徑(classpath)上所指定的類庫。blog

注意:該類加載器也被稱爲系統類加載器,開發者能夠直接使用該類加載器。若開發者沒有自定義類加載器,程序默認使用該類加載器。開發

各類類加載器並非孤立的,而是互相配合使用。虛擬機

在java虛擬機中,各類類加載器配合使用的模型就是雙親委派模型

雙親委派模型

雙親委派模型的工做流程所有在ClassLoader的loadClass()方法中執行:

@Override 
protected Class<?> loadClass(String name, boolean resolve) 
        throws ClassNotFoundException { 
    Class<?> c = findLoadedClass(name); 

  // 檢查須要加載的類是否已經被加載過
    if (c == null) { 
        try { 
             // 若沒有加載,則調用父加載器的loadClass()方法
            if (parent != null) { 
                c = parent.loadClass(name, false); 
            }else{ 
                // 若父類加載器爲空,則默認使用啓動類加載器做爲父加載器
                c=findBootstrapClassOrNull(name); 
            } 
        } catch (ClassNotFoundException e) { 
            // 若父類加載器加載失敗會拋出ClassNotFoundException, 
            //說明父類加載器沒法完成加載請求 
        } 
        if(c==null){ 
            // 在父類加載器沒法加載時 
            // 再調用自己的findClass方法進行類加載 
            c=findClass(name); 
        } 
    } 
    if(resolve){ 
        resolveClass(c); 
    } 
    return c; 
}
複製代碼

若一個類加載器收到了類加載請求:

步驟:

  • 把該類加載請求委派給父加載器父完成,而不是本身去加載;(每層的類加載器都是如此,所以全部的類加載請求最終都會交由啓動類加載器去加載)
  • 只用當父類加載器反饋本身沒法完成該加載請求時,自加載器纔會本身加載。

優勢:

Java類隨着它的類加載器一塊兒具有了一種帶優先級的層次關係。

相關文章
相關標籤/搜索