溫馨提示×

溫馨提示×

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

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

java虛擬機的類加載機制介紹

發(fā)布時間:2021-09-01 10:50:33 來源:億速云 閱讀:139 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要介紹“java虛擬機的類加載機制介紹”,在日常操作中,相信很多人在java虛擬機的類加載機制介紹問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”java虛擬機的類加載機制介紹”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

類加載的時機

    說到類加載的時機,就不得不提類加載的生命周期了,加載——驗證——準備——解析——初始化——使用——卸載。七個階段。書中說解析和初始化的位置可以互換,是為了支持java語言的動態(tài)綁定導(dǎo)致的。這點我暫時不知道,不做研究先。

    不過我們一起來探討下類加載什么情況下會立即觸發(fā)初始化呢。

    java虛擬機規(guī)范中明確規(guī)定了五種情況必須立即對類進行初始化:

  1. 遇到new、getstatic、putstatic或者invokestatic 這4條字節(jié)碼指令時,如果類沒有初始化,則會先觸發(fā)類進行初始化。這4條指令對應(yīng)最常見的java代碼場景為:使用new關(guān)鍵字實例化對象的時候、讀取或者設(shè)置一個類的靜態(tài)變量(static final修飾的變量不算,因為在編譯期就把該變量放入常量池中了)、調(diào)用一個類的靜態(tài)方法。

  2. 使用java.lang.reflect包的方法對類進行放射調(diào)用時,如果沒有初始化,會優(yōu)先初始化

  3.  初始化一個類的時候,如果發(fā)現(xiàn)其父類還沒有初始化,會優(yōu)先初始化其父類

  4.  當虛擬機啟動時,用戶指定一個要執(zhí)行的主類(main()方法的類),會優(yōu)先初始化主類

  5. 如果java.lang.invoke.MethodHandle實例最后解析的結(jié)果REF_getstatic、REF_putstatic、ERF_invokestatic的方法句柄,且這個方法的句柄所對應(yīng)的類沒有初始化,則會優(yōu)先初始化。

    以上的5中場景成為對一個類的主動引用,除此之外,所以引用類的方式都不會觸發(fā)初始化,成為被動引用。

下面看看代碼:

package chapter.Seven;

class SuperClass {  static{    System.out.println("SuperClass init");  }  public static int value=123;  public static final String NAME="QuellanAn";}

class SubClass extends SuperClass {  static{    System.out.println("SubClass init");  }}

public class NotInitialzation {  public static void main(String[] args){    System.out.println(SubClass.value);  }}

    main方法中調(diào)用“SubClass.value”,value是SuperClass的靜態(tài)變量。所以觸發(fā)了上面第一點,所以SuperClass類會被初始化。雖然是通過SubClass調(diào)用的,但是SubClass類沒有觸發(fā)上面5點的任何一點,所以不會進行初始化。

結(jié)果:

SuperClass init123

    在看一個,就改下main()方法,其他都不不變。

public class NotInitialzation {  public static void main(String[] args){    System.out.println(SubClass.NAME);  }}

    同樣根據(jù)上面第一點,可以發(fā)現(xiàn),NAME是靜態(tài)常量,在編譯期(形成class文件的時候)就已經(jīng)存在常量池中了。所以SuperClass也是不會初始化的。

結(jié)果:

QuellanAn

    上面的例子可以很好的看出什么時候?qū)@個類初始化了什么時候沒有。有且只有上面那5中情況才會對類型進行初始化。

    另外說一點,當一個類在初始化時,要求其父類全部都已經(jīng)初始化了,但是在接口初始化時,并不要求父接口全部初始化,只需要在正真用到哪個父接口就初始化那個。

java虛擬機的類加載機制介紹

類加載的過程

    類加載的過程分為7個階段,但重要的前面加載——驗證——準備——解析——初始化前面5個。下面來依次的說明下。

加載

    在加載階段,虛擬機需要完成以下3件事:

    1. 通過一個類的全限定名來獲取定義此類的二進制字節(jié)流。(全限定名:第一次聽到這個詞有點摸不著頭腦,網(wǎng)上查了一下,才知道是有點絕對路徑的意思,比如

Java類包的定名:com.linux.struct.sort.bubblesort,從最原始最上層的地方援引到具體的對象,這就是全限定名了)

    2.將二進制字節(jié)流中所代表的的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)運行時結(jié)構(gòu)。

    3.在內(nèi)存中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這個的類的各個數(shù)據(jù)的訪問入口。

驗證

    驗證是連接階段的第一步,驗證的目的主要是為了確保class文件轉(zhuǎn)換成的二進制文件流中包含的信息符合當前虛擬機的要求。并且不會危害到虛擬機的安全。

    驗證階段主要完成4個階段的驗證工作:文件格式檢驗、元數(shù)據(jù)校驗、字節(jié)碼校驗、符號引用校驗。

準備

    準備階段,是正式為類的變量分配內(nèi)存空間并設(shè)置類變量初始值的階段。這些變量所使用內(nèi)存都將在方法區(qū)中分配。需要注意的是:這個階段今次進行內(nèi)存分配的進包含類變量,而不包含實例變量。實例變量將在對象實例化時隨著對象一起分配到j(luò)ava堆中。并且這里說的初始值“通常情況”下是數(shù)據(jù)類型的零值,比如:

public static int value=123;

    在value準備階段過后的初始值為0,而不是123.value值在初始化的時候才會被賦值成123.因為把value賦值為123的putstatic指令在初始化后才執(zhí)行。

解析

    解析階段是虛擬機將常量池內(nèi)的符號引用替換成直接引用的過程。

java虛擬機的類加載機制介紹

初始化

    初始化階段,執(zhí)行類構(gòu)造器<clinit>()方法。會進行類變量的賦值和靜態(tài)語句塊(static{}快)的執(zhí)行。

到此,關(guān)于“java虛擬機的類加載機制介紹”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

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

AI