類載入

孔德昌發表於2020-12-11

類載入過程

虛擬機器只載入程式執行時所需要的的類檔案。

JVM不是一開始就把所有的類都載入進記憶體中,而是隻有第一次遇到某個需要執行的類時才會載入,且只載入一次

類載入的過程主要分為三個部分:

  1. 載入

    Java 將位元組碼資料從不同的資料來源讀取到 JVM 中,並對映為 JVM 認可的資料結構(Class 物件),這裡的資料來源可能是各種各樣的形態,比如 jar 檔案,class 檔案,甚至是網路資料來源等

  2. 連結

    類定義資訊轉入 JVM 執行的過程中

  3. 初始化

    執行類初始化的程式碼邏輯,使用雙親委派機制避免重複載入 Java 型別。

而連結又可以細分為三個小部分:

  1. 驗證

    JVM 需要核驗位元組資訊是符合 Java 虛擬機器規範

  2. 準備

    建立類或者介面中的靜態變數,並初始化靜態變數的初始值。分配所需要的記憶體空間,不會去執行更進一步的 JVM 指令。

  3. 解析

    ​ 常量池中的符號引用替換為直接引用。類,介面,方法和欄位等各方面的解析。

    img

最後是初始化。

類載入器

引導類載入器 (啟動類載入器)(根類載入器)(bootstrap class loader)(沒有對應ClassLoader物件,c++編寫)(沒有父子關係)

平臺類載入器(擴充套件類載入器)(ExtClassLoader)

系統類載入器(應用類載入器)(AppClassLoader)

JVM的類載入機制主要有如下3種。

  1. 全盤負責:所謂全盤負責,就是當一個類載入器負責載入某個Class時,該Class所依賴和引用其他Class也將由該類載入器負責載入,除非顯示使用另外一個類載入器來載入。

  2. 雙親委派:父類載入器試圖載入該Class,只有在父類載入器無法載入該類時才嘗試從自己的類路徑中載入該類。通俗的講,就是某個特定的類載入器在接到載入類的請求時,首先將載入任務委託給父載入器,依次遞迴,如果父載入器可以完成類載入任務,就成功返回;只有父載入器無法完成此載入任務時,才自己去載入。

  3. 快取機制。快取機制將會保證所有載入過的Class都會被快取,當程式中需要使用某個Class時,類載入器先從快取區中搜尋該Class,只有當快取區中不存在該Class物件時,系統才會讀取該類對應的二進位制資料,並將其轉換成Class物件,存入緩衝區中。這就是為很麼修改了Class後,必須重新啟動JVM,程式所做的修改才會生效的原因。

    除了引導類載入器以外,每一個類載入器都有一個父類載入器。

自定義類載入器(通常是為了加密)

繼承ClassLoader類,重寫findClass方法

父類的loadClass()方法將類載入委託給父類載入器,當該類未載入且父類載入器無法載入時,才會呼叫findClass()方法。

public class MyClassLoader extends ClassLoader{
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //return super.findClass(name);
        // 實現該方法必須要做到以下幾點
        /****
        	* 1.來自本地檔案系統或其他來源的類載入及位元組碼。
        	* 2.呼叫ClassLoader父類的defineClass()方法,向jvm提供位元組碼。
        	*/
    }
}

相關文章