1. 程式人生 > >虛擬機類加載機制

虛擬機類加載機制

常量池 什麽 reflect 反射 lec 綁定 png 虛擬機啟動 字節

1.類加載的時機

類從被加載到虛擬機內存開始,到卸載出內存為止,它整個生命周期包括了:加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using) 和 卸載(Unloading)七個階段。 其中驗證、準備和解析三個部分統稱為連接(Linking)。這七個階段的發生順序如下所示。

技術分享

其中加載、驗證、準備、初始化和卸載這五個階段的順序是確定的。而解析階段不一定:它在某些情況下可以在初始化階段之後再開始,這是為了支持java語言的運行時綁定。

加載階段在什麽情況下進行,虛擬機規範中並沒有強制約束,這點可以交個虛擬機的具體實現來自由把握。對於初始化階段,虛擬機規範則是嚴格規定了有且只有四種情況必須立即對類進行”初始化”

1).遇到new、getstatic、putstatic或invokestatic這4條字節碼指令時,如果類沒有進行過初始化,則需要先觸發其初始化。常見的場景為:new關鍵字實例化對象、讀取或設置一個類的靜態字段(被final修飾、已在編譯期把結果放入常量池的靜態字段除外)的時候、以及調用一個類的靜態方法的時候。

2).使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行初始化,則需要先觸發其初始化。

3).當初始化一個類的時候,如果發現其父類還沒有進行初始化,則需要先觸發其父類的初始化。

4).當虛擬機啟動時,用戶需要指定一個要執行的主類(包含main()方法的那個類),虛擬機會先初始化這個主類。

接口的加載過程和類的加載過程稍有一些不同:接口也有初始化過程,接口與類有區別的是第三種:當一個類在初始化時,要求其父類全部都已經初始化過了,但是一個接口在初始化時,並不要求其父接口全部都完成了初始化,只有在真正使用到父接口的時候才會初始化。

虛擬機類加載機制