天天看點

JVM之詳解類加載器與雙親委派模型

類加載器

類加載器就是根據指定全限定名稱,将class檔案加載到JVM記憶體中,轉為Class對象。JAVA中的類加載器有下面這四種:

1、啟動類加載器(Bootstrap ClassLoader):負責加載Java的核心庫(<JAVA_HOME/lib>)中的類,用原生C++寫的,并不內建自java.lang.ClassLoader;

2、擴充類加載器(Extensions ClassLoader):負責加載Java擴充擴庫(<JAVA_HOME>/lib/ext)中的類;

3、應用程式類加載器(Application ClassLoader):也叫系統類加載器,它根據應用的類路徑(CLASSPATH)來加載類;

4、自定義類加載器(Custom ClassLoader):應用開發人員可以通過繼承java.lang.ClassLoader的方式,來實作自己的類加載器,已滿足定制化需求。

模型:

JVM之詳解類加載器與雙親委派模型

測試代碼:

public class Test {

    public static void main(String[] args) {

        // System ClassLoader
        System.out.println(ClassLoader.getSystemClassLoader());
        // Extensions ClassLoader
        System.out.println(ClassLoader.getSystemClassLoader().getParent());
        // Bootstrap ClassLoader
        System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());
    }
}
           
JVM之詳解類加載器與雙親委派模型

可以清楚看出,測試類Test,是有AppClassLoader加載的,它的父加載器是ExtClassLoader,而ExtClassLoader的父加載器,列印結果為null,是因為Bootstrap ClassLoader是由C++實作的,這裡擷取不到。

雙親委派模型

如果一個類加載器收到類加載的請求,該加載器不會自己去加載,而且委派給父類加載器去加載,父類加載器收到加載請求後,同樣會繼續向上委派,直到最頂層的Bootst ClassLoader。如果父加載器可以加載此類,則成功傳回,否則會将加載任務回退給子類加載器去加載。

1、為什麼要采用雙親委派模型

假設某黑客,自定義了一個類java.lang.String,擁有和JDK自帶的String類同樣的功能,隻不過修改了其中的equals方法,加入了一些病毒代碼,并且通過自定義的類加載器,加載到JVM中。如果沒有雙親委派模型,JVM可能會誤以為黑客的這個“String”類是正确的,程式是使用equals方法時,調用了黑客的String類,執行了其中的病毒代碼。另外一個原因就是保證同一個類隻會被加載一次,假設兩個加載器都收到的加載請求,如果不采用雙親委派,這個類将會被他們分别加載,而在雙親委派模型下,向上委派,加載一次後,不會加載第二次了。