1. 程式人生 > >JVM的類載入器

JVM的類載入器

什麼是類載入器?

ClassLoader就是類載入器,這個回答是否機智?(鬼臉)
言歸正傳:還記得在上一篇關於類載入機制的文章中,有一個步驟叫做載入,其中有一個動作就是“通過一個類的全限定名來載入描述此類的二進位制流檔案”。實現這個動作的程式碼就叫做類載入器

類與類載入器

兩個描述類的二進位制流檔案相同,這兩個類是否就一樣?答案是:不一樣

判斷兩個類是否相同的前提是:描述類的二進位制流檔案相同,並且載入類的類載入器相同

雙親委派系統

對JVM來說總共有兩種類載入器:啟動類載入器(Bootstrap ClassLoader),這個是使用C++編寫的,屬於jvm的一部分。另一個是其他類載入器,由java語言實現,並且繼承與java.lang.ClassLoader

對於Java開發者來說,總共有三種類載入器:

  1. 啟動類載入器
  2. 擴充套件類載入器
  3. 程式類載入器

啟動類載入器,前面已經介紹過一些。啟動類載入器主要負責載入存放在
<JAVA_HOME>/lib下面的或者被Xbootclasspath指定的路徑中的類庫

擴充套件類載入器,她負責載入<JAVA_HOME>/lib/ext下面的目錄

程式類載入器,這個類載入器便是ClassLoader中getSystemClassLoader()方法的返回值,負責載入使用者指定路徑上的類庫。

我們日常程式大部分是由這三種載入器配合使用的。這些載入器之間遵循雙親委派系統的載入模型:
在這裡插入圖片描述

在雙親委派系統模型中,要求除了啟動類載入之外的所有載入器都擁有自己的父類載入器。並且這些父子關係不是以繼承的關係維持,而是以組合的模式(屬於一種設計模式,不懂得小夥伴可以自行查詢

)形成的。

雙親委派系統的類載入器的工作模式是什麼樣的呢?

當一個類載入器收到一個類載入請求的時候,首先會把這個請求委派給父類,每一個層次的類載入器都是如此,因此所有的請求最紅都會被傳遞到啟動類載入器。在父類反饋自己無法完成這個請求的時候才會讓子類來處理這個類載入的任務。

在前面,我們提到過,判斷兩個類是否相等的條件是:二進位制流檔案相同,類載入器相同。
正式由於雙親委派模型的這種委派特性,才使得我們整個系統中所使用的基礎類保持一致。假設沒有這種模型,我們有一個基礎類java.lang.Object,在系統的A模組,我們使用ClassLoaderA載入;在系統的B模組我們使用ClassLoaderB載入,就會導致兩個模組中的Object不一樣,這將會是非糟糕的結果。

下面展示雙親委派模型的實現細節:

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;
}
--------------------- 
特別鳴謝:
作者:zhaoenweiex 
原文:https://blog.csdn.net/zhaoenweiex/article/details/63289374?utm_source=copy