jvm類載入子系統

qq_43549500發表於2020-12-13

jvm類載入子系統

類載入子系統作用

1.類載入子系統負責從檔案系統或者網路中載入class檔案,class檔案在檔案開頭有特定的檔案標識即16進位制CA FE BA BE;

2.載入後的Class類資訊存放於一塊成為方法區的記憶體空間。除了類資訊之外,方法區還會存放執行時常量池資訊,可能還包括字串字面量和數字常量(這部分常量資訊是Class檔案中常量池部分的記憶體對映)

JVM記憶體結構圖:其中類載入器的工作範圍只限於下圖的左半部分,不包含呼叫構造器例項化物件

img

https://img2020.cnblogs.com/blog/1846149/202004/1846149-20200401105500017-801589677.png

3.ClassLoader只負責class檔案的載入,至於它是否可以執行,則由Execution Engine決定

4.如果呼叫構造器例項化物件,則其例項存放在堆區

載入模組

1.通過一個類的全限定明獲取定義此類的二進位制位元組流;

2.將這個位元組流所代表的的靜態儲存結構轉化為方法區的執行時資料;

3.在記憶體中生成一個代表這個類的java.lang.Class物件,作為方法區這個類的各種資料的訪問入口

連結模組分為三塊,即驗證、準備、解析

img

驗證

1.目的在於確保Class檔案的位元組流中包含資訊符合當前虛擬機器要求,保證被載入類的正確性,不會危害虛擬機器自身安全。

2.主要包括四種驗證,檔案格式驗證,源資料驗證,位元組碼驗證,符號引用驗證。

準備

1.為類變數分配記憶體並且設定該類變數的預設初始值,即零值;

2.這裡不包含用final修飾的sttic,因為final在編譯的時候就會分配了,準備階段會顯式初始化;

3.之類不會為例項變數分配初始化,類變數會分配在方法去中,而例項變數是會隨著物件一起分配到java堆中。

解析

1.將常量池內的符號引用轉換為直接引用的過程。

2.事實上,解析操作網晚會伴隨著jvm在執行完初始化之後再執行

3.符號引用就是一組符號來描述所引用的目標。符號應用的字面量形式明確定義在《java虛擬機器規範》的class檔案格式中。直接引用就是直接指向目標的指標、相對偏移量或一個間接定位到目標的控制程式碼

4.解析動作主要針對類或介面、欄位、類方法、介面方法、方法型別等。對應常量池中的CONSTANT_Class_info/CONSTANT_Fieldref_info、CONSTANT_Methodref_info等。

初始化模組,初始化階段就是執行類構造器方法clinit()的過程

1.clinit()即“class or interface initialization method”,注意他並不是指構造器init()

2.此方法不需要定義,是javac編譯器自動收集類中的所有類變數的賦值動作和靜態程式碼塊中的語句合併而來。

JVM中表示兩個class物件是否為同一個類

1.在jvm中表示兩個class物件是否為同一個類存在的兩個必要條件

類的完整類名必須一致,包括包名

即使類的完整類名一致,同時要求載入這個類的ClassLoader(指ClassLoader例項物件)必須相同;是引導類載入器、還是定義類載入器

2.換句話說,在jvm中,即使這兩個類物件(class物件)來源同一個Class檔案,被同一個虛擬機器所載入,但只要載入它們的ClassLoader例項物件不同,那麼這兩個類物件也是不相等的.

3.對類載入器的引用,JVM必須知道一個型別是有啟動類載入器載入的還是由使用者類載入器載入的。如果一個型別由使用者類載入器載入的,那麼jvm會將這個類載入器的一個引用作為型別資訊的一部分儲存在方法區中。當解析一個型別到另一個型別的引用的時候,JVM需要保證兩個型別的載入器是相同的。

java程式對類的使用方式分為:主動使用和被動使用,即是否呼叫了clinit()方法

主動使用在類載入系統中的第三階段initialization即初始化階段呼叫了clinit()方法

而被動使用不會去呼叫

主動使用,分為七種情況

1.建立類的例項

2.訪問某各類或介面的靜態變數,或者對靜態變數賦值

3.呼叫類的靜態方法

4.反射 比如Class.forName(com.dsh.jvm.xxx)

5.初始化一個類的子類

6.java虛擬機器啟動時被標明為啟動類的類

7.JDK 7 開始提供的動態語言支援:java.lang.invoke.MethodHandle例項的解析結果REF_getStatic、REF_putStatic、REF_invokeStatic控制程式碼對應的類沒有初始化,則初始化

7 開始提供的動態語言支援:java.lang.invoke.MethodHandle例項的解析結果REF_getStatic、REF_putStatic、REF_invokeStatic控制程式碼對應的類沒有初始化,則初始化

除了以上七種情況,其他使用java類的方式都被看作是對類的被動使用,都不會導致類的初始。
參考文章:https://www.cnblogs.com/yanl55555/p/12611133.html

相關文章