1. 程式人生 > >如何將class檔案載入在JVM中。

如何將class檔案載入在JVM中。

    如下圖所示是ClassLoader載入一個class檔案到JVM時需要經過的步驟。
    
    第一個階段是找到.class檔案並把這個檔案包含的位元組碼載入到記憶體中。
    第二個階段又可以分為三個步驟,分別實位元組碼驗證、Class類資料結構及相應的記憶體分配和最後的符號表的連結。
    第三個階段是類中靜態屬性和初始化賦值,以及靜態塊的執行等。

載入位元組碼到記憶體

    其實在抽象類ClassLoader中沒有定義如何去載入,如何去找到指定類並且把他的位元組碼載入到記憶體需要的子類中去實現,也就是要實現findClass()方法。我們看一下子類URLClassLoader是如何實現findClass的,在URLClassLoader中通過一個URLClassPath類幫助取得要載入的class檔案位元組流,而這個URLClassPath定義了到哪裡去找這個class檔案,如果找到了這個class檔案,在讀取他的byte位元組流,通過呼叫defineClass()方法來建立類物件。
    這個實現機制如同inputStream和OutputStream一樣,只是定義了讀取檔案的機制和形式,並沒有定義從哪裡和如何讀取他。
    我們再看看URLClassLoader類的建構函式,可以發現必須要指定一個URL資料才能夠建立URLClassLoader物件,也就是必須要指定這個ClassLoader預設到哪個目錄下去查詢class檔案。
    這個URL陣列也是建立URLClassPath物件的必要條件。從URLClassPath的名字中就可以發現他是通過URL的形式來表示ClassPath路徑的。
    在建立URLClassPath物件時會根據傳過來的URL陣列中的路徑來判斷是檔案還是jar包,根據路徑的不同分別建立FileLoader或者JarLoader,或者使用預設的載入器。當JVM呼叫findClass時由這幾個載入器來將class檔案的位元組碼載入到記憶體中。
    如何設定每個ClassLoader的搜尋路徑呢?下表所示是Bootstrap ClassLoader、ExtClassLoader和AppClassLoader的引數形式。

ClassLoader型別 引數選項 說明
Bootstrap ClassLoader -Xbootclasspath: 設定Bootstrap ClassLoader的搜尋路徑

-Xbootclasspath/a:

-Xbootclasspath/p:

把路徑新增到已存在Bootstrap ClassLoader搜尋路徑的後面

把路徑新增到已存在Bootstrap ClassLoader搜尋路徑的前面

ExtClassLoader -Djava.ext.dirs 設定ExtClassLoader的搜尋路徑
AppClassLoader -Djava.class.path=-cp 或-classpath 設定AppClassLoader的搜尋路徑

    在上面的引數設定中,最常用到的就是設定classpath的環境變數,因為通常都是讓Java執行指定的程式。如果在通過命令列執行一個類時出現NoClassDefFoundError錯誤,那麼很可能是沒有指定classpath所致,或者指定了classpath但是沒有指明包名。

驗證與解析

  •     位元組碼驗證,類裝入器對於類的位元組碼要做許多檢測,以確保格式正確、行為正確。
  •     類準備,在這個階段準備代表每個類中定義的欄位、方法和實現介面所必須的資料結構。
  •     解析,在這個階段類裝入器裝入類所引用的其他所有類。可以用許多方式引用類,如超類、介面、欄位、方法簽名、方法中使用的本地變數。

初始化Class物件

    在類中包含的靜態初始化器都被執行,在這一階段末尾靜態欄位被初始化為預設值。