文章目錄
- 一、介紹
- 二、加載階段
- 三、連接階段
- 1、驗證階段
- 2、準備階段
- 3、解析階段
- 四、初始化階段
一、介紹
類的生命周期描述了一個類加載、連接(驗證、準備和解析)、初始化、使用、卸載的整個過程。
二、加載階段
- 加載(Loading)階段第一步是類加載器根據類的權限定名通過不同的渠道以二進制的方式獲取字節碼信息。程序員可以使用Java代碼擴展不同的渠道。
- 類加載器在加載完類之后,Java虛擬機會將字節碼的信息保存到方法區中。生成一個InstanceKlass對象,保存類的所有信息,里面還包含實現特定功能比如多態的信息。
- 同時,Java虛擬機還會再堆中生成一份與方法區中的數據類似的java.lang.Class對象。作用是在Java代碼中去獲取類的信息以及存儲靜態字段的數據。
- 對于開發者來說,只需要訪問堆中的Class對象而不需要訪問方法區中的所有信息。這樣Java虛擬機就能很好地控制開發者訪問數據的范圍。
查看內存中的對象:
- 使用JDK自帶的hsdb工具查看Java虛擬機內存信息。工具位于JDK安裝目錄下lib文件夾中的sa-jdi.jar中。
- 啟動命令:java -cp sa-jdi.jar sun.jvm.hotspot.HSDB
三、連接階段
1、驗證階段
- 連接(Linking)階段的第一個環節是驗證,驗證的主要目的是檢測Java字節碼文件是否遵守了《Java虛擬機規范》中的約束。這個階段一般不需要程序員參與。
- 主要包含如下四個部分,詳見《Java虛擬機規范》:
- 文件格式驗證,比如文件是否以0xCAFEBABE開頭,主次版本號是否滿足當前Java虛擬機版本要求。
- 元信息驗證,例如類必須有父類(super不能為空)
- 驗證程序執行指令的語義,比如方法內的指令執行到一半強行跳轉到其他方法中去。
- 符號引用驗證,例如是否訪問了其他類中private的方法等。
- 文件格式驗證,比如文件是否以0xCAFEBABE開頭,主次版本號是否滿足當前Java虛擬機版本要求。
2、準備階段
- 準備階段為靜態變量(static)分配內存并設置初始值。
- 準備階段只會給靜態變量賦初始值,而每個基本類型和引用類型都有其初始值。
- final修飾的基本數據類型的靜態變量,準備階段直接會將代碼中的值進行賦值。
- 準備階段只會給靜態變量賦初始值,而每個基本類型和引用類型都有其初始值。
3、解析階段
- 解析階段主要是將常量池中的符號引用替換為直接引用。
- 符號引用就是在字節碼文件中使用編號來訪問常量池中的內容。
四、初始化階段
- 初始化階段會執行靜態代碼塊中的代碼,并為靜態變量賦值。
- 初始化階段會執行字節碼文件中clinit部分的字節碼指令。clinit方法中的執行順序與Java中編寫的順序是一致的。
哪幾種方式會導致類的初始化:
- 添加 -XX:+TraceClassLoading參數可以打印出加載并初始化的類。
- 訪問一個類的靜態變量或者靜態方法,注意變量是final修飾的并且等號右邊是常量不會觸發初始化。