Java虛擬機JVM學習03 連接過程:驗證、准備、解析
類被加載后,就進入連接階段。
連接就是將已經讀入到內存的類的二進制數據合並到虛擬機的運行時環境中去。
連接階段三個步驟:驗證、准備和解析。
類的驗證
類的驗證內容:
1.類文件的結構檢查
確保類文件遵從Java類文件的固定格式。
2.語義檢查
確保類本身符合Java語言的語法規定,比如驗證final類型的類沒有子類,以及final類型的方法沒有被覆蓋。
注意,語義檢查的錯誤在編譯器編譯階段就會通不過,但是如果有程序員通過非編譯的手段生成了類文件,其中有可能會含有語義錯誤,此時的語義檢查主要是防止這種沒有編譯而生成的class文件引入的錯誤。
3.字節碼驗證
確保字節碼流可以被Java虛擬機安全地執行。
字節碼流代表Java方法(包括靜態方法和實例方法),它是由被稱作操作碼的單字節指令組成的序列,每一個操作碼后都跟着一個或多個操作數。
字節碼驗證步驟會檢查每個操作碼是否合法,即是否有着合法的操作數。
4.二級制兼容性的驗證
確保相互引用的類之間的協調一致。
例如,在Worker類的gotoWork()方法中會調用Car類的run()方法,Java虛擬機在驗證Worker類時,會檢查在方法區內是否存在Car類的run()方法,假如不存在(當Worker類和Car類的版本不兼容就會出現這種問題),就會拋出NoSuchMethodError錯誤。
類的准備
在准備階段,Java虛擬機為類的靜態變量分配內存,並設置默認的初始值。
例如對於以下Sample類,在准備階段,將為int類型的靜態變量a分配4個字節的內存空間,並且賦予默認值0,為long類型的靜態變量b分配8個字節的內存空間,並且賦予默認值0。
package com.mengdd.classloader; public class Sample { private static int a = 1; private static long b; static { b = 2; } }
類的解析
在解析階段,Java虛擬機會把類的二級制數據中的符號引用替換為直接引用。
例如在Worker類的gotoWork()方法中會引用Car類的run()方法。
public void gotoWork() { car.run();// 這段代碼在Worker類的二進制數據中表示為符號引用 }
在Worker類的二進制數據中,包含了一個對Car類的run()方法的符號引用,它由run()方法的全名和相關描述符組成。
在解析階段,Java虛擬機會把這個符號引用替換為一個指針,該指針指向Car類的run()方法在方法區內的內存位置,這個指針就是直接引用。
參考資料
聖思園張龍老師Java SE系列視頻教程。