您好,登錄后才能下訂單哦!
這篇文章主要介紹“java虛擬機的類加載機制介紹”,在日常操作中,相信很多人在java虛擬機的類加載機制介紹問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”java虛擬機的類加載機制介紹”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
類加載的時機
說到類加載的時機,就不得不提類加載的生命周期了,加載——驗證——準備——解析——初始化——使用——卸載。七個階段。書中說解析和初始化的位置可以互換,是為了支持java語言的動態綁定導致的。這點我暫時不知道,不做研究先。
不過我們一起來探討下類加載什么情況下會立即觸發初始化呢。
java虛擬機規范中明確規定了五種情況必須立即對類進行初始化:
遇到new、getstatic、putstatic或者invokestatic 這4條字節碼指令時,如果類沒有初始化,則會先觸發類進行初始化。這4條指令對應最常見的java代碼場景為:使用new關鍵字實例化對象的時候、讀取或者設置一個類的靜態變量(static final修飾的變量不算,因為在編譯期就把該變量放入常量池中了)、調用一個類的靜態方法。
使用java.lang.reflect包的方法對類進行放射調用時,如果沒有初始化,會優先初始化
初始化一個類的時候,如果發現其父類還沒有初始化,會優先初始化其父類
當虛擬機啟動時,用戶指定一個要執行的主類(main()方法的類),會優先初始化主類
如果java.lang.invoke.MethodHandle實例最后解析的結果REF_getstatic、REF_putstatic、ERF_invokestatic的方法句柄,且這個方法的句柄所對應的類沒有初始化,則會優先初始化。
以上的5中場景成為對一個類的主動引用,除此之外,所以引用類的方式都不會觸發初始化,成為被動引用。
下面看看代碼:
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方法中調用“SubClass.value”,value是SuperClass的靜態變量。所以觸發了上面第一點,所以SuperClass類會被初始化。雖然是通過SubClass調用的,但是SubClass類沒有觸發上面5點的任何一點,所以不會進行初始化。
結果:
SuperClass init123
在看一個,就改下main()方法,其他都不不變。
public class NotInitialzation { public static void main(String[] args){ System.out.println(SubClass.NAME); }}
同樣根據上面第一點,可以發現,NAME是靜態常量,在編譯期(形成class文件的時候)就已經存在常量池中了。所以SuperClass也是不會初始化的。
結果:
QuellanAn
上面的例子可以很好的看出什么時候對這個類初始化了什么時候沒有。有且只有上面那5中情況才會對類型進行初始化。
另外說一點,當一個類在初始化時,要求其父類全部都已經初始化了,但是在接口初始化時,并不要求父接口全部初始化,只需要在正真用到哪個父接口就初始化那個。
類加載的過程
類加載的過程分為7個階段,但重要的前面加載——驗證——準備——解析——初始化前面5個。下面來依次的說明下。
加載
在加載階段,虛擬機需要完成以下3件事:
1. 通過一個類的全限定名來獲取定義此類的二進制字節流。(全限定名:第一次聽到這個詞有點摸不著頭腦,網上查了一下,才知道是有點絕對路徑的意思,比如
Java類包的定名:com.linux.struct.sort.bubblesort,從最原始最上層的地方援引到具體的對象,這就是全限定名了)
2.將二進制字節流中所代表的的靜態存儲結構轉化為方法區運行時結構。
3.在內存中生成一個代表這個類的java.lang.Class對象,作為方法區這個的類的各個數據的訪問入口。
驗證
驗證是連接階段的第一步,驗證的目的主要是為了確保class文件轉換成的二進制文件流中包含的信息符合當前虛擬機的要求。并且不會危害到虛擬機的安全。
驗證階段主要完成4個階段的驗證工作:文件格式檢驗、元數據校驗、字節碼校驗、符號引用校驗。
準備
準備階段,是正式為類的變量分配內存空間并設置類變量初始值的階段。這些變量所使用內存都將在方法區中分配。需要注意的是:這個階段今次進行內存分配的進包含類變量,而不包含實例變量。實例變量將在對象實例化時隨著對象一起分配到java堆中。并且這里說的初始值“通常情況”下是數據類型的零值,比如:
public static int value=123;
在value準備階段過后的初始值為0,而不是123.value值在初始化的時候才會被賦值成123.因為把value賦值為123的putstatic指令在初始化后才執行。
解析
解析階段是虛擬機將常量池內的符號引用替換成直接引用的過程。
初始化
初始化階段,執行類構造器<clinit>()方法。會進行類變量的賦值和靜態語句塊(static{}快)的執行。
到此,關于“java虛擬機的類加載機制介紹”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。