欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JVM虛擬機(jī)的類加載機(jī)制

 更新時(shí)間:2023年08月14日 10:22:08   作者:haihui_yang  
這篇文章主要介紹了詳解JVM虛擬機(jī)的類加載機(jī)制,虛擬機(jī)把描述類的數(shù)據(jù)從 Class 文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)、轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機(jī)直接使用的 Java 類型,這就是虛擬機(jī)的類加載機(jī)制,需要的朋友可以參考下

1、什么是虛擬機(jī)的類加載機(jī)制?

虛擬機(jī)把描述類的數(shù)據(jù)從 Class 文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)、轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機(jī)直接使用的 Java 類型。

這就是虛擬機(jī)的類加載機(jī)制(通俗一點(diǎn)講就是把 Class 轉(zhuǎn)成虛擬機(jī)可以使用的 Java 類型,轉(zhuǎn)換過(guò)程中會(huì)有校驗(yàn)、解析和初始化的操作)。

2、類的生命周期:

類從被加載到虛擬機(jī)內(nèi)存開(kāi)始,到卸載出內(nèi)存為止,它的生命周期包括:加載(Loading)、驗(yàn)證(Verification)、準(zhǔn)備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸載(Unloading)七個(gè)階段。其中,驗(yàn)證、準(zhǔn)備、解析三個(gè)部分統(tǒng)稱為連接(Linking)。如下圖所示:

類的生命周期

圖中需要注意的地方:加載、驗(yàn)證、準(zhǔn)備、初始化和卸載這五個(gè)階段具有確定的順序。

這個(gè)確定的順序是指"開(kāi)始",即驗(yàn)證階段必須等加載開(kāi)始之后才能開(kāi)始,準(zhǔn)備階段開(kāi)始必須在驗(yàn)證開(kāi)始之后。而 “進(jìn)行” 和 “完成” 的順序則不一定,這些階段通常都是可以互相交叉地混合式進(jìn)行的,通常會(huì)在一個(gè)階段執(zhí)行的過(guò)程中調(diào)用、激活另外一個(gè)階段。

3、觸發(fā)類初始化的條件(有且只有五種情況):

  • new 一個(gè)對(duì)象的時(shí)候、讀取或設(shè)置一個(gè)類的靜態(tài)字段(放入常量池的靜態(tài)字段除外:被 final 修飾的 static 變量)的時(shí)候,以及調(diào)用一個(gè)類的靜態(tài)方法的時(shí)候。
  • 反射調(diào)用的時(shí)候。
  • 子類初始化觸發(fā)父類初始化。
  • 執(zhí)行的主類(包含 main() 方法的那個(gè)類)。
  • 當(dāng)使用 JDK 1.7 的動(dòng)態(tài)語(yǔ)言支持時(shí),如果一個(gè) java.lang.invoke.MethodHandle 實(shí)例最后的解析結(jié)果是 REF_getStatic、REF_putStatic、REF_invokeStatic 的方法句柄的時(shí)候。

下面幾個(gè)例子是類的被動(dòng)引用,不會(huì)觸發(fā)類的初始化:

(1)通過(guò)子類引用父類的靜態(tài)字段,不會(huì)導(dǎo)致子類初始化

public class SuperClass {
    static {
        System.out.println("SuperClass init!");
    }
    public static int value = 123;
}
public class SubClass extends SuperClass {
    static {
        System.out.println("SubClass init!");
    }
}
public class NotInitialization {
    public static void main(String[] args) {
        System.out.println(SubClass.value);//通過(guò)子類引用父類的靜態(tài)字段,不會(huì)導(dǎo)致子類初始化
    }
}

(2)通過(guò)數(shù)組定義來(lái)引用類,不會(huì)觸發(fā)此類的初始化

public class NotInitialization {
    public static void main(String[] args) {
        SuperClass[] superClassArray = new SuperClass[10]; // 通過(guò)數(shù)組定義來(lái)引用類,不會(huì)觸發(fā)此類的初始化
    }
    // 這段代碼不會(huì)輸出 "SuperClass init!",即沒(méi)有觸發(fā) SuperClass 的初始化
}

(3)常量在編譯階段會(huì)存入調(diào)用類的常量池中,本質(zhì)上并沒(méi)有直接引用到定義常量的類,因此不會(huì)觸發(fā)定義常量的類的初始化

public class ConstClass {
    static {
        System.out.println("ConstClass init!");
    }
    public static final String HELLO_WORLD = "hello world";
}
public class NotInitialization {
    public static void main(String[] args) {
        System.out.println(ConstClass.HELLO_WORLD); // 引用常量池的變量不會(huì)觸發(fā)定義常量的類的初始化
    }
    // 不會(huì)輸出 "ConstClass init!"
}

4、類加載的過(guò)程 加載

  • 加載階段,虛擬機(jī)通過(guò)一個(gè)類的全限定名來(lái)獲取定義此類的二進(jìn)制流,然后把二進(jìn)制流的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu),最后在內(nèi)存中生成一個(gè)對(duì)象,作為方法區(qū)這個(gè)類各種數(shù)據(jù)的訪問(wèn)入口。
  • 驗(yàn)證(非常重要但非必要)

驗(yàn)證的目的在于確保 Class 文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬機(jī)自身的安全。(假如自己編寫(xiě)的及第三方庫(kù)都已經(jīng)被反復(fù)使用和驗(yàn)證過(guò),那么,可以考慮使用 -Xverify:none 參數(shù)關(guān)閉大部分的類驗(yàn)證機(jī)制,以縮短虛擬機(jī)類加載的時(shí)間)

驗(yàn)證階段大致會(huì)完成以下四個(gè)驗(yàn)證動(dòng)作:

(1)文件格式驗(yàn)證

(2)元數(shù)據(jù)驗(yàn)證

(3)字節(jié)碼驗(yàn)證

(4)符號(hào)引用驗(yàn)證

  • 準(zhǔn)備

準(zhǔn)備階段是給類成員變量設(shè)置初始值(數(shù)據(jù)類型的零值)。

這里的類成員變量指被 static 修飾的變量;初始值指數(shù)據(jù)類型的零值;而常量(被 static final 修飾的變量)會(huì)初始化為具體的值。

例如:

public static final int value = 123;
// 虛擬機(jī)在準(zhǔn)備階段就會(huì)根據(jù) ConstantValue 的設(shè)置將 value 賦值為 123。

數(shù)據(jù)類型的零值:

數(shù)據(jù)類型的零值

  • 解析

解析階段主要做的事情是虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換成直接引用。

Java 中編譯時(shí) java.lang.NoSuchFieldError java.lang.NoSuchMethodError 、 java.lang.IllegalAccessError 等異常就是在解析階段拋出的。

  • 初始化

初始化階段是類加載過(guò)程的最后一步。前面我們提到,準(zhǔn)備階段會(huì)給類變量設(shè)置初始零值,而在初始化階段,則是給類變量執(zhí)行代碼里真正賦值的時(shí)候。

  • 賦值操作由所有類變量的賦值動(dòng)作和靜態(tài)語(yǔ)句塊中的語(yǔ)句共同產(chǎn)生,編譯器收集的順序是由語(yǔ)句在源文件中出現(xiàn)的順序所決定的,靜態(tài)語(yǔ)句塊中只能訪問(wèn)到定義在靜態(tài)語(yǔ)句塊之前的變量,定義在它之后的變量,在前面的靜態(tài)語(yǔ)句塊可以賦值,但是不能訪問(wèn),例如:
public class Test {
    static {
        i = 0; // 靜態(tài)語(yǔ)句塊可以給后面定義的類變量賦值,但是不能訪問(wèn)(編譯器會(huì)報(bào) "非法向前引用" )
        // System.out.println(i); Illegal forward reference.
    }
    static int i = 1;
}

初始化階段的注意事項(xiàng):

(1)靜態(tài)成員變量初始化在靜態(tài)方法之前( static {}  中都是變量賦值);

(2)父類初始化在子類之前

(3)執(zhí)行接口的初始化的時(shí)候不需要先執(zhí)行父接口的初始化,只有當(dāng)父接口中定義的變量使用時(shí),父接口才會(huì)初始化;

(4)虛擬機(jī)會(huì)保證一個(gè)類的初始化方法在多線程環(huán)境中被正確地加鎖、同步:保證了在同一個(gè)類加載器下,一個(gè)類型只會(huì)初始化一次。

到此這篇關(guān)于詳解JVM虛擬機(jī)的類加載機(jī)制的文章就介紹到這了,更多相關(guān)JVM類加載機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java設(shè)計(jì)模式之Iterator模式介紹

    Java設(shè)計(jì)模式之Iterator模式介紹

    所謂Iterator模式,即是Iterator為不同的容器提供一個(gè)統(tǒng)一的訪問(wèn)方式。本文以java中的容器為例,模擬Iterator的原理。需要的朋友可以參考下
    2013-07-07
  • SpringCloud中的Feign遠(yuǎn)程調(diào)用接口傳參失敗問(wèn)題

    SpringCloud中的Feign遠(yuǎn)程調(diào)用接口傳參失敗問(wèn)題

    這篇文章主要介紹了SpringCloud中的Feign遠(yuǎn)程調(diào)用接口傳參失敗問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Mybatis攔截器打印sql問(wèn)題

    Mybatis攔截器打印sql問(wèn)題

    這篇文章主要介紹了Mybatis攔截器打印sql問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 怎么在AVD上安裝apk軟件

    怎么在AVD上安裝apk軟件

    執(zhí)行 Windows 開(kāi)始菜單 => 所有程序 => 附件 => 命令提示符 或通過(guò) Win+R 組合鍵調(diào)出 運(yùn)行 對(duì)話框輸入cmd 單擊確定即可
    2013-09-09
  • 實(shí)例講解Java的Spring框架中的AOP實(shí)現(xiàn)

    實(shí)例講解Java的Spring框架中的AOP實(shí)現(xiàn)

    這篇文章主要介紹了Java的Spring框架中的AOP實(shí)現(xiàn)實(shí)例,AOP面向切面編程其實(shí)也可以被看作是一個(gè)設(shè)計(jì)模式去規(guī)范項(xiàng)目的結(jié)構(gòu),需要的朋友可以參考下
    2016-04-04
  • 理解Java訪問(wèn)權(quán)限控制

    理解Java訪問(wèn)權(quán)限控制

    這篇文章主要幫助大家深入的理解Java訪問(wèn)權(quán)限控制,為何需要訪問(wèn)控制權(quán)限,本文給出了解釋,感興趣的小伙伴們可以參考一下
    2016-02-02
  • Java項(xiàng)目Guava包?HashMultimap使用及注意事項(xiàng)

    Java項(xiàng)目Guava包?HashMultimap使用及注意事項(xiàng)

    guava基本上可以說(shuō)是java開(kāi)發(fā)項(xiàng)目中,大概率會(huì)引入的包,今天介紹的主角是一個(gè)特殊的容器HashMultmap,可以簡(jiǎn)單的將它的數(shù)據(jù)結(jié)構(gòu)理解為Map<K,?Set<V>>,今天主要介紹下基礎(chǔ)的知識(shí)點(diǎn)?HashMultmap級(jí)使用,感興趣的朋友一起看看吧
    2022-05-05
  • JMeter配置元件詳解

    JMeter配置元件詳解

    JMeter提供了豐富的配置元件,常用的包括參數(shù)化配置元件、HTTP請(qǐng)求默認(rèn)值、HTTP信息頭管理器、計(jì)數(shù)器等,本文就詳細(xì)的介紹一下這些元件的使用,感興趣的可以了解一下
    2021-12-12
  • Java可變個(gè)數(shù)形參的方法實(shí)例代碼

    Java可變個(gè)數(shù)形參的方法實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于Java可變個(gè)數(shù)形參的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02
  • 淺談Java中格式化輸出

    淺談Java中格式化輸出

    這篇文章主要介紹了Java中格式化輸出,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04

最新評(píng)論