基礎
- 類加載器:用于裝載字節碼文件(.class文件)
- 運行時數據區:用于分配存儲空間
- 執行引擎:執行字節碼文件或本地方法
- 垃圾回收器:用于對JVM中的垃圾內容進行回收
類加載器 :JVM只會運行二進制文件,類加載器的作用就是將字節碼文件加載到JVM中,從而讓Java程序能夠啟動起來。
類加載器分類:
- 啟動類加載器(BootStrap ClassLoader):加載JAVA_HOME/jre/lib目錄下的庫。
- 擴展類加載器(ExtClassLoader):主要加載JAVA_HOME/jre/lib/ext目錄中的類。
- 應用類加載器(AppClassLoader):用于加載classPath下的類。
- 自定義類加載器(CustomizeClassLoader):自定義類繼承ClassLoader,實現自定義類加載規則。
雙親委派模型
加載某一個類,先委托上一級的加載器進行加載,如果上級加載器也有上級,則會繼續向上委托,如果該類委托上級沒有被加載,子加載器嘗試加載該類。
使用雙親委派機制的作用:
- 通過雙親委派機制可以避免某一個類被重復加載,當父類已經加載后則無需重復加載,保證唯一性。
- 為了安全,保證類庫API不會被修改。
舉例:
類裝載的執行過程
類從加載到虛擬機中開始,直到卸載為止,它的整個生命周期包括了:加載、驗證、準備、解析、初始化、使用和卸載這7個階段。其中,驗證、準備和解析這三個部分統稱為連接(linking)。
加載:
- 通過類的全名,獲取類的二進制數據流。
- 解析類的二進制數據流為方法區內(元空間)的數據結構(Java類模型) 。
- 創建java.lang.Class類的實例(堆),表示該類型。作為方法區這個類的各種數據的訪問入口 。
如圖:
驗證: 驗證類是否符合 JVM規范,安全性檢查
主要驗證以下4項:
(1)文件格式驗證
(2)元數據驗證
(3)字節碼驗證
(4)符號引用驗證——Class文件在其常量池會通過字符串記錄自己將要使用的其他類或者方法,檢查它們是否存在,如圖:
其中,前三項都是格式檢查,如——文件格式是否錯誤、語法是否錯誤、字節碼是否合規。
準備: 為類變量分配內存并設置類變量初始值
- static變量,分配空間在準備階段完成(設置默認值),賦值在初始化階段完成
- static變量是final的基本類型,以及字符串常量,值已確定,賦值在準備階段完成
- static變量是final的引用類型,那么賦值也會在初始化階段完成
解析: 把類中的符號引用轉換為直接引用。
比如:方法中調用了其他方法,方法名可以理解為符號引用,而直接引用就是使用指針直接指向方法。
初始化: 對類的靜態變量,靜態代碼塊執行初始化操作。
- 如果初始化一個類的時候,其父類尚未初始化,則優先初始化其父類。
- 如果同時包含多個靜態變量和靜態代碼塊,則按照自上而下的順序依次執行。
- 如果子類訪問父類靜態變量,只觸發父類初始化。
使用:
JVM 開始從入口方法開始執行用戶的程序代碼
- 調用靜態類成員信息(比如:靜態字段、靜態方法)
- 使用new關鍵字為其創建對象實例
綜上,類裝載構成為:
- 加載:查找和導入class文件
- 驗證:保證加載類的準確性
- 準備:為類變量分配內存并設置類變量初始值
- 解析:把類中的符號引用轉換為直接引用
- 初始化:對類的靜態變量,靜態代碼塊執行初始化操作
- 使用:JVM 開始從入口方法開始執行用戶的程序代碼
- 卸載:當用戶程序代碼執行完畢后,JVM便開始銷毀創建的Class對象。