【Java】類加載流程

類加載

類加載

加載

“加載”是“類加載”(Class Loading)過程中的一個階段
在加載階段,虛擬機完成三件事情:

  • 通過一個類的全限定名來獲取定義此類的二進制字節流。
  • 將這個字節流所代表的靜態存儲結構轉化爲方法區的運行時數據結構。
  • 在內存中生成一個代表這個類的java.lang.Class對象,作爲方法區這個類的各種數據的訪問入口。

驗證

驗證是連接階段的第一步,這一階段的目的是爲了確保Class文件的字節流包含的信息符合當前虛擬機的要求,並且不會危害虛擬機自身的安全

驗證階段大致會完成4個階段的檢查動作:

  • 文件格式驗證
    驗證字節流是否符合Class文件格式的規範,並且能被當前版本的虛擬機處理;
  • 元數據驗證
    對字節碼描述的信息進行語義分析,以保證其描述的信息符合Java語言規範的要求;
  • 字節碼驗證
    整個驗證過程中最複雜的一個階段,主要目的通過數據流和控制流分析,確定程序語義是合法的、符合邏輯的。在第二階段對元數據信息中的數據類型做完校驗後,這個階段將對類的方法體進行校驗分析,保證被校驗類的方法在運行時不會做出危害虛擬機安全的事件。
  • 符號引用驗證
    發生在虛擬機引用轉化爲直接引用的時候,這個轉化動作將在連接的第三個階段——解析階段中發生。
    符號引用驗證的目的是確保解析動作能正常執行

準備

準備階段是正式爲類變量分配內存並設置類變量初始值的階段,這些變量所使用的內存都將在方法區中進行分配

解析

虛擬機將常量池內的符號引用替換爲直接引用的過程;

解析階段中的直接引用和符號引用的關聯
符號引用(Symbolic Reference):符號引用一組符號來描述所引用的目標,符號是任何形式的字面量,只要使用時能無歧義地定位到目標即可。符號引用與虛擬機實現的內存佈局無關,引用的目標並不一定已經加載到內存中。符號引用的字面量形式明確定義在Java虛擬機規範的Class文件格式中。
直接引用(Direct Reference):直接引用可以是直接指向目標的指針、相對偏移量或是一個能簡介定位到目標的句柄。**直接引用是和虛擬機實現的內存佈局相關的,同一個符號在不同虛擬機實例上翻譯出來的直接引用一般不會相同。**如果有了直接引用,那引用的目標必定已經在內存中存在。

初始化

類加載過程的最後一步;在準備階段,變量已經賦過一次系統要求的初始值,而在初始化階段,則根據程序猿通過程序制定的主觀計劃去初始化類變量和其他資源,或者從另外一個角度表達:初始化階段是執行類構造器<clinit>()方法的過程

類加載器

類加載階段中的“通過一個類的全限定名來獲取描述此類的二進制字節流”這個動作放到Java虛擬機外部去實現,以便讓應用程序自己決定如何去獲取所需要的類。實現這個動作的代碼模塊成爲“類加載器”。

類與類加載器

對於任意一個類,都需要由加載它的類加載器和這個類本身一同確立其在Java虛擬機中的唯一性,每一個類加載器,都擁有一個獨立的類名稱空間。即:比較兩個類是否“相等”,只有在這兩個類是由同一個類加載器加載的前提下才有意義,否則,即使這兩個類來源於同一個Class文件,被同一個虛擬機加載,只要加載它們的類加載器不同,那這兩個類就必定不相等。

雙親委派模式

絕大部分Java程序會使用一下三種系統提供的類加載器:

  • 啓動類加載器(Bootstrap ClassLoader)
  • 擴展類加載器(Extension ClassLoader)
  • 應用程序類加載器(Application ClassLoader)

雙親委派模式

雙親委派模式工作過程
如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到頂層的啓動類加載器中,只有當父類加載器反饋自己無法完成這個加載請求(它的搜索範圍中沒有找到所需的類)時,子加載器纔會嘗試自己去加載。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章