1.類加載機制
虛擬機把描述類的數據從class文件加載到內存,並對數據進行校驗、轉換、解析、初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制
Java是使用雙親委派模型來進行類加載的,這樣能夠有效確保一個類的全局唯一性,當程序中出現多個限定名相同的類時,類加載器在執行加載時,始終只會加載其中的某一個類
雙親委派模型工作過程可以參考我的博文:
2.類加載步驟
加載
在加載過程會完成3件事情:
通過一個類的全限定名獲取該類的二進制流
將該二進制流中的靜態存儲結構轉化爲方法區運行時數據結構
在內存中生成該類的class對象,作爲該類的數據訪問入口
驗證
驗證類數據信息是否符合JVM規範,是否是一個有效的字節碼文件,主要完成下面4種驗證
文件格式驗證:驗證字節流是否符合class文件的規範,如主次版本號是否在當前虛擬機範圍內,常量池中的常量是否有不被支持的類型
元數據驗證:對字節碼描述的信息進行語義分析,如這個類是否有父類,是否繼承了不被繼承的類等
字節碼驗證:是整個驗證過程中最複雜的一個階段,通過驗證數據流和控制流的分析,確定程序語義是否正確,主要針對方法體的驗證,如方法中的類型轉換是否正確,跳轉指令是否正確等
符號引用驗證:這個在後面的解析過程中發生,主要是爲了確保解析動作能正確執行
準備
準備階段是爲類的靜態變量分配內存並將其初始化爲默認值,這些內存都將在方法區中進行分配。準備階段不分配類中的實例變量的內存,實例變量將會在對象實例化時隨着對象一起分配在Java堆中
解析
該階段主要完成符號引用到直接引用的轉換動作。解析動作並不一定在初始化動作完成之前,也可能在初始化之後
注意:
驗證 準備 解析階段又合稱爲鏈接階段,鏈接階段要做的是將加載到JVM中的二進制字節流的類數據信息合併到JVM的運行時狀態中
初始化
初始化階段是類加載過程的最後一步 , 前面的幾個階段, 除了在加載階段用戶應用程序可以通過自定義類加載器參與之外, 其餘動作完全由虛擬機主導和控制。到了初始化階段, 才真正開始執行類中定義的 Java程序代碼
爲靜態變量賦值,執行static代碼塊,static代碼塊只有JVM能夠調用,如果是多線程需要同時初始化一個類,僅僅只能允許其中一個線程對其執行初始化操作,其它線程必須等待
3.類加載器
實現通過類的權限定名獲取該類的二進制字節流的代碼塊叫做類加載器
啓動類加載器:用來加載java核心類庫,無法被Java程序直接引用
擴展類加載器:用來加載Java的擴展庫。Java虛擬機的實現會提供一個擴展庫目錄,該類加載器在此目錄中查找並加載Java類
系統類加載器:它根據Java應用的類路徑來加載Java類。一般來說,Java應用的類都是由它來加載的,可以通過ClassLoader.getSystemClassLoader()來獲取它
用戶自定義類加載器:通過繼承java.lang.ClassLoader類的方式實現