中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java的JVM類加載機制是什么

發布時間:2023-04-20 11:31:14 來源:億速云 閱讀:125 作者:iii 欄目:開發技術

本篇內容介紹了“Java的JVM類加載機制是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

    Java虛擬機把描述類的數據從Class文件加載到內存,并對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這個過程被稱作虛擬機的類加載機制。當Java程序運行時,Java虛擬機會按需加載類,即在程序需要使用某個類時才會加載該類。

    類的生命周期如下圖:

    Java的JVM類加載機制是什么

    JVM的類加載機制包括加載連接( 驗證準備解析)、初始化 3個階段。

    加載(Loading)

    加載(Loading) 階段主要是查找并加載字節碼文件,這個文件可以是來自本地文件系統、網絡、jar包等地方。加載后,生成一個對應的Class對象。

    加載類時會做以下工作:

    1. 根據類的全限定名查找并讀取類的二進制數據。類的二進制數據可以來自文件、網絡、數據庫等各種數據源。

    2. 將類的二進制數據轉換成方法區內部的數據結構。在轉換的過程中,JVM會對類的二進制數據進行解析和校驗。

    3. 在方法區內存儲該類的相關信息,包括類的名稱、修飾符、常量池、字段描述符、方法描述符、接口描述符、方法表等。

    4. 生成一個代表該類的Class對象,并將該對象存放在JVM的堆內存中。Class對象包含了類的各種信息,可以用于創建類的實例、獲取類的方法和字段等操作。

    需要注意的是,在加載類的過程中,JVM會遵循一定的雙親委派機制,即先委派給父類加載器嘗試加載,如果父類加載器無法加載,則由當前類加載器進行加載。這樣可以保證類的加載不會重復,避免出現類似的類被多次加載的情況。有關類加載器可以查看我之前的文章。

    加載階段與連接階段的部分動作(如一部分字節碼文件格式驗證動作)是交叉進行的,加載階段尚未完成,連接階段可能已經開始,但這些夾在加載階段之中進行的動作,仍然屬于連接階段的一部分,這兩個階段的開始時間仍然保持著固定的先后順序。

    連接(Linking)

    連接階段是Java虛擬機將類文件中的符號引用轉換為直接引用的過程,會對字節碼文件進行驗證、準備、解析。

    • 驗證(Verification):在這個階段,JVM會對字節碼進行驗證,以確保其符合Java虛擬機規范,并且不會對虛擬機造成安全威脅。驗證的內容包括靜態分析、字節碼驗證、符號引用驗證等。如果驗證失敗,JVM會拋出VerifyError異常。

    • 準備(Preparation):在這個階段,JVM會為類的靜態變量分配內存,并將其初始化為默認值(零值)。這個階段不會執行任何Java代碼,只是為靜態變量分配內存空間。例如將int類型的靜態變量賦值為0。

    public static int staticValue = 123;

    準備階段初始化只是將靜態變量初始化為默認值,比如上面這段代碼,不同數據類型都有其默認值,初始化是只是將staticValue賦予默認值0,也就是staticValue = 0,只有在初始化階段才會將staticValue賦值為123,也就是staticValue = 123。但是如果是staticValue是個常量public static final int staticValue = 123,準備階段才會將staticValue賦值為123。

    • 解析(Resolution):在這個階段,JVM會將類、接口、字段和方法的符號引用解析為直接引用符號引用是指用來描述某個類、字段或方法的名稱和類型的符號,而直接引用則是指直接指向內存中的具體位置的引用。解析的過程包括將類或接口的符號引用解析為直接引用、將字段的符號引用解析為直接引用、將類中方法的符號引用解析為直接引用。

    初始化(Initialization)

    初始化階段是指在類被首次主動使用時執行的階段,虛擬機會執行類的初始化代碼,包括靜態變量的賦值和靜態代碼塊的執行等操作。

    初始化階段是類加載的最后一個階段,在該階段,JVM會執行以下操作:

    1. 執行靜態變量賦值操作:在這個階段,JVM會對所有的靜態變量進行初始化并賦值。這些靜態變量的值通常在類定義中已經被明確定義了,JVM會根據定義進行相應的賦值操作。

    2. 執行靜態代碼塊:如果類定義中包含有靜態代碼塊,那么在該階段JVM會執行這些靜態代碼塊中的代碼。

    3. 調用類的初始化方法:在Java程序中,可以使用static關鍵字來定義一個類的靜態初始化方法(即static void methodName())。在該階段,JVM會調用這個類的靜態初始化方法。

    類初始化的時機

    類初始化時機包括以下四種情況:

    • 創建該類的實例對象時,例如使用 new 關鍵字創建對象,類的初始化將被觸發 如果一個類是程序執行的入口類(即包含 main() 方法的類),那么也會觸發該類的初始化操作。

    • 子類初始化會觸發父類初始化:當一個子類被初始化時,其父類也會被初始化。這意味著,如果一個類沒有被使用,那么它的父類也不會被初始化。

    • 當調用類的靜態方法(不包括final方法和private方法)或訪問類的靜態字段(不包括final字段)時,類的初始化將被觸發。

    • 當使用反射API對類進行某些操作時(例如使用Class.forName()方法加載類、調用Class.newInstance()方法創建對象、調用Method.invoke()方法調用方法等),類的初始化將被觸發。

    初始化是線程安全的JVM保證一個類的初始化只會由一個線程去執行,其他線程需要等待該線程完成后才能訪問該類。

    下面用一個簡單的Java代碼示例,展示JVM類加載機制中初始化階段的示例

    public class MyClass {
    
        // 靜態變量
        public static String staticStr = "Hello, world!";
    
        static {
            System.out.println("MyClass is initialized.");
        }
    
        // 構造方法
        public MyClass() {
            System.out.println("MyClass constructor is called.");
        }
    
        // 靜態方法
        public static void staticMethod() {
            System.out.println("MyClass staticMethod is called.");
        }
    }

    在上述代碼中,類MyClass包含一個靜態變量staticStr、一個靜態代碼塊和一個構造方法,以及一個靜態方法staticMethod。當程序首次使用MyClass類時,JVM將會觸發MyClass類的初始化階段。可以通過下面的代碼來測試類的初始化:

    public class Test {
        public static void main(String[] args) {
            System.out.println(MyClass.staticStr); // 調用靜態變量,觸發類初始化
            MyClass.staticMethod(); // 調用靜態方法,觸發類初始化
            MyClass obj = new MyClass(); // 創建對象,觸發類初始化
        }
    }

    在上面的代碼中,首先輸出了MyClass類的靜態變量staticStr,此時會觸發MyClass類的初始化;然后調用了靜態方法staticMethod,同樣會觸發MyClass類的初始化;最后創建了一個MyClass對象,也會觸發MyClass類的初始化。運行上述代碼,可以看到以下輸出:

    MyClass is initialized.
    Hello, world!
    MyClass staticMethod is called.
    MyClass constructor is called.

    輸出結果表明,MyClass類的初始化確實在首次使用該類時被觸發,包括靜態變量、靜態代碼塊、靜態方法和構造方法都被執行了。

    此外,如果一個類是另一個類的子類,那么在使用子類時,父類也會被初始化。例如:

    public class MyBaseClass {
        static {
            System.out.println("MyBaseClass is initialized.");
        }
    }
    
    public class MySubClass extends MyBaseClass {
        static {
            System.out.println("MySubClass is initialized.");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            MySubClass obj = new MySubClass(); // 創建子類對象,觸發父類和子類初始化
        }
    }

    在上述代碼中,當創建MySubClass類的對象時,將會觸發MyBaseClass和MySubClass類的初始化。運行上述代碼,可以看到以下輸出:

    MyBaseClass is initialized.
    MySubClass is initialized.

    “Java的JVM類加載機制是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    安国市| 东莞市| 襄樊市| 万全县| 沙河市| 双江| 永州市| 六安市| 七台河市| 永平县| 三亚市| 咸阳市| 元氏县| 万源市| 砚山县| 平泉县| 宁波市| 天全县| 马公市| 赤峰市| 澳门| 东城区| 肥东县| 镇平县| 宝丰县| 天峨县| 荆州市| 福清市| 永济市| 陕西省| 阳江市| 万年县| 溧水县| 伊通| 冕宁县| 临湘市| 遂川县| 哈密市| 南昌县| 亚东县| 紫云|