再來一遍JVM 類加載機制

類加載的流程  加載->連接->初始化->使用->卸載       連接過程: 驗證->準備->解析

第一個階段:加載

 什麼情況下必須進行加載呢?

使用關鍵字 new  getStatic putStatic invokestatic  這四個字節碼指令的時候
對類型進行反射調用的時候
初始化一個類,但是發現還沒有初始化父類的時候
虛擬機啓動時,主類啓動的時候
java動態語言支持,解析結果爲獲取類型的靜態參數的時候
JDK8中 default定義的接口方法的實現類初始化的時候,必須先觸發接口方法的初始化

 

 

 

 

 

 

 

加載過程虛擬機執行的動作

 1.根據類的全限定名稱,獲取類的二進制字節流

 2.將類型的靜態存儲結構放入到方法區中(所以靜態屬性是最早進入方法區的)

 3.在內存中生成該類型的Class對象,作爲該類型的訪問入口

第二個階段:驗證

文件格式驗證:對於Class文件的規定的格式的驗證
元數據驗證:類型的類關係驗證,比如是否有父類,父類的繼承時候符合要求等語義校驗
字節碼驗證:保證字節碼能按照順序進行工作,不會因爲意外跳轉到別的類型字節碼指令上去,保證字節碼的合法性
符號引用驗證:類型的可訪問行。類型屬性的可訪問行等,確保解析行爲能執行

 

 

 

 

 

 

第三階段:準備

  爲類中定義的變量(靜態變量)分配內存,並設置類變量的初始值,這部分內存會在java8之後放在堆內存中而不是方法區。

第四階段:解析

  將常量池內的符號引用替換爲直接引用的過程。

  符號引用:使用一組符號描述引用的對象

  直接引用:直接指向目標的指針,或者能間接定位到目標的句柄。

第五階段:初始化

  JVM 執行類中編寫的java代碼

 

類加載器:

  通過一個類型的全限定名去獲取類型的二進制字節流  這個動作是放在JVM之外執行的,讓程序自己決定如何去加載這個類。

  一個類型的唯一性是由類加載器和類本身來確定的,也就是說  類是同一個類,但是類加載器不同的話,運行程序判斷這兩個類型依舊不屬於同一個類型。

雙親委派模型:

  類加載器的分類:

啓動類加載器
擴展類加載器
應用程序類加載器
自定義類加載器

 

 

 

 

這些類加載器的層級依次降低

雙親委派模型:除了頂層啓動類加載器之外,其他的加載器都必須有自己的父類加載器。爲什麼又叫“雙親委派”呢,因爲類加載器之間的關係不是父子關係,是組合關係,組合起來就是被加載類的雙親。(你就想象這個類的父親娶了一個跟你差不多年齡的後媽就行了,但是你還得叫她 媽)

工作流程:如果一個類加載器收到了一個類加載的請求,首先他自己不會去加載這個類,會讓它的父類加載器去加載這個類型,每一層都是這麼來搞得,因此最後加載的請求就會傳到最頂層的啓動類加載器,只有當父類加載器反饋說我不能加載這個類的時候,子類加載器才進行加載。

優點:Java的類會隨着類加載器的加載過程具備一種帶優先級的層級關係。也就是說一個類型在JVM中肯定能確保是同一個類,(如果這裏有疑問可以看上面類加載器的介紹,如何確定唯一的一個類型)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章