1. 程式人生 > >5分鐘掌握jvm 類的載入機制

5分鐘掌握jvm 類的載入機制


類的載入分為以下幾個階段

載入->驗證->準備->解析->初始化->使用->解除安裝

           |         連結階段     |

           ------------------------

速記法:家宴準備,姐使用蟹

1.載入,在虛擬機器方法區中生成一個這個類的物件,作為方法區中這個類各種資訊的訪問入口,這個載入檔案的來源可以是本地某個目錄,war包,或者是網路來源,或者是執行時生成的類的資訊。

2.驗證,驗證階段主要是驗證檔案型別是否符合虛擬機器的要求,是否合法,是否會損害虛擬機器的安全,驗證雖然重要,但不是必須的。可以通過Xverifynone引數關閉大部分驗證。

驗證主要驗證一下幾個部分:1.檔案格式驗證,魔術是否為0xCAFEBABE開頭,版本號是否在當前虛擬機器可執行範圍內,常量池中是否有不支援的型別。
 2.元資料驗證,分析語義是否符合java規範。
 3.位元組碼驗證,驗證語義是否合法符合邏輯。
 4.引用符號驗證,保證解析能夠正確執行。
 速記法,服(符號)侍(格式)源(元資料)碼(位元組碼)
3.準備,準備階段會給類的靜態變數分配記憶體(方法區中),並設定初始值,需要注意的是這時候的初始值並不是在程式碼裡賦值的初始值,而是規定的零值,例如,static int a=1,在這個階段並不是賦值為1,而是賦值為0,賦值為1的操作是在後邊類的初始化階段才會做的,但是final型別的會在此階段舊賦值為給定值,例如 static final a=1,這個a變數在此階段已經是1。

4.解析
,解析階段是將常量池中的符號引用替換為直接引用的過程,針對類或介面,欄位,方法,介面方法,方法型別,方法控制代碼,和呼叫點限定符進行引用。

5.初始化,初始化是真正執行原始碼中編寫的static 變數賦值語句的過程,初始化會執行類的構造器方法<clinit>()方法,類的構造器方法是由編譯器自動收集類中所有static變數和static語句塊中的語句合併產生的,順序是按原始碼中出現的先後順序,因此靜態語句塊無法訪問定義在其後邊的靜態變數。

虛擬機器會保證在子物件的初始化方法執行之前父類的類構造器方法會自動執行,不用顯示的呼叫,同時虛擬機器可以保證多個執行緒同時載入一個類,只有一個執行緒能夠執行類的構造方法。
虛擬機器規定只有5中情況必須對類進行初始化,
1.遇到 new getstatic,putstatic,invokestatic這四條指令,如果類還沒有初始化,要對類進行初始化,這四條指令對應的java程式碼通常是,new關鍵字例項化物件,讀取或設               置一個類的靜態屬性,以及呼叫一個類的靜態方法時。
2.使用java.lang.reflect包的方法對類進行反射呼叫的時候,如果類沒進行過初始化要先初始化。
3.當初始化一個類的時候,如果其父類還沒有初始化,要對其初始化。
4.當啟動虛擬機器時,要執行的main方法所在的類要初始化。
5.當使用動態語言支援時,如果一個java.lang.invoke.MethodHandle例項最後解析的結果是REF_getstatic,REF_putstatic,invokeStatic的方法控制代碼,並且這個方法控制代碼對應             的類沒有進行過初始化,則要出發初始化。
速記法
:囑(主main)咐(父類)反(反射)動(動態語言時)得死(四條指令) 囑咐反動得死
以上五種都是主動引用,除了主動引用被動引用是不會出發類的初始化的,被動引用包含
1.通過子類引用父類的靜態屬性,子類不會出發初始化。
2.通過陣列來引用類不會觸發類的初始化。
3.引用類的靜態常量,final static 修飾的變數不會觸發類的初始化

速記法:常(常量)叔(陣列)父(父類) 常叔父

更多精彩內容請關注微信公眾號 IT農廠【ITFF01】