java虛擬機(java virtual Machine)是用於運行java應用程序的虛構個計算機.java
是java程序"一次編譯,處處運行"的關鍵,java程序編譯時,不是直接編譯成目標機器的機器碼,而是編譯成.class的二級制的字節碼文件,再由目標機器上的JVM虛擬機把.class文件翻譯爲對應機器的機器碼執行.程序員
加載
"加載"就是將.class文件讀到內存中,「加載」的動做主要在classLoader.cpp(指包含類的子類)和classFileParser.cpp文件中實現數據結構
讀取二進制字節流多線程
JVM規範沒有限制從本地讀取.class文件,因此能夠從jar包或者其餘方式來讀取.最終會返回ClassFileStream對象的指針
將字節流轉換爲運行時的數據結構函數
獲取到指針後,會建立實例,而且解析ClassFileStream結構: 1.讀取魔數並校驗 校驗jdk版本信息 2.讀取常量池引用 包括常量和符號應用,符號引用指父類,接口,字段,放法等 3.讀取訪問標識並校驗 類的類型class仍是interface,訪問類型public 仍是抽象的 4.獲取類的全限定名 讀取當前類的索引,並在常量池中找到當前類的全限定名,讀取常量池時,會得到常量池句柄,會標識全限定名的地址 5.獲取父類或者接口信息,若是有繼承或者實現,則需先加載父類和接口,若是已經加載則直接獲取它們的句柄記錄到本類中,並簡單校驗類名 6.讀取字段信息和方法信息加載到本類的信息中,以後會評估類的大小,類加載完成以後,大小不會發生改變
生成java.lang.Class對象編碼
1.計算虛擬函數表和接口函數表的大小 2.建立instanceKlass對象(.class文件對應的全部類信息) 3.建立Java鏡像類並初始化靜態域,通知JVM加載完成,方法區建立該類的元數據
驗證spa
加載和驗證是交叉進行的,驗證在各個階段都是存在的,驗證二進制字節流表明的字節碼文件是否合格,主要從一下幾方面判斷:線程
文件格式:參看class文件格式詳解,通過文件格式驗證以後的字節流才能進入方法區分配內存來存儲。 元數據驗證:是否符合java語言規範 字節碼驗證:數據流和控制流的分析,這一步最複雜 符號引用驗證:符號引用轉化爲直接引用時(解析階段),檢測對類自身之外的信息進行存在性、可訪問性驗證
準備
「準備」階段是爲class或者interface中的靜態變量賦初始值,若是常量無初始值,則默認賦值爲java基本數據類型的默認值翻譯
類型 | 描述 |
---|---|
byte | 8位補碼錶示,默認值爲0 |
byte | 用8位補碼錶示,初始化爲0 |
short | 用16位補碼錶示,初始化爲0 |
int | 用32位補碼錶示,初始化爲0 |
long | 用64位補碼錶示,初始化爲0L |
char | 用16位補碼錶示,初始化爲」u0000」,使用UTF-16編碼 |
float | 初始化爲正0 |
double | 初始化爲正0 |
boolean | 初始化爲0 |
returnAddress | 初始化爲字節碼指令的地址,用於配合異常處理特殊指令 |
解析
解析階段是虛擬機將常量池內的符號引用替換爲直接引用的過程指針
符號引用(Symbolic References):符號引用以一組符號來描述所引用的目標,符號能夠是任何形式的字面量,只要使用時能無歧義地定位到目標便可。
直接引用(Direct References):直接引用能夠是直接指向目標的指針、相對偏移量或是一個能間接定位到目標的句柄。若是有了直接引用,那麼引用的目標必定是已經存在於內存中。
1.類或接口的解析
2.字段解析
3.類方法解析
4.接口方法解析
初始化
類初始化階段是類加載過程的最後一步,到了這個階段才真正開始執行類中定義的Java程序代碼(或者說是字節碼)。在準備階段,變量已經賦過一次系統要求的初始值,而在初始化階段,則根據程序員經過程序制定的主觀計劃去初始化類變量和其餘資源。