基本過程:
- 根據類的全限定名稱加載定義類的二進制字節流。
- 將字節流代表的靜態存儲結構轉化為方法區的運行時數據結構
- 內存中生成一個代表這個類的java.lang.Class對象,作為方法去這個類的各種數據訪問入口
數組類本身不通過類加載器創建,由Java虛擬機直接創建,數組類的元素類型由類加載器加載。
數組類的元素類型:數組去掉所有維度後的類型,
文件格式驗證:
- 0xCAFEBABY 魔數開頭;
- 主次版本號當前虛擬機可處理;
- 常量類型;
- 索引執行類型;
- utf8編碼數據類型,
元數據驗證:字節碼描述信息語義分析:
- 是否有父類;
- 父類是否繼承了final修飾的類;
- 非抽型類是否實現了父類或接口中需要實現的方法;
- 類中的字段、方法的覆蓋,重載矛盾;
字節碼驗證:通過語義流及控制流分析確定程序予以的合法性,正確性,方法體分析驗證。
符號引用驗證:虛擬機將符號引用轉化為直接引用時候,解析階段,對類自身以外信息進行匹配性驗證
- 符號引用中通過字符描述的全限定名是否能找到對應的類;
- 指定類中是否存在符合方法字段的描述符,及簡單名稱所描述的方法和字段;
- 符號引用中類,字段,方法的訪問性。
准備:在方法區中為類變量分配內存及設置類變量初始值。
- 初始值通常為數據類型的零值,final修飾的值直接初始化為相應值。
- 類變量為static修飾的變量,區分於實例變量。
解析:虛擬機將常量池中的符號引用替換為直接引用過程 CONSTANT_Class_info,CONSTANT_Fieldref_info,CONSTANT_Methodref_info..
- 符號引用:以一組符號來描述所引用的目標,任何形式的字面量,只要使用時能無歧義的定位到目標,,與虛擬機內存實現無關,無關引用目標是否加載。
- 直接引用:直接指向目標的指針,偏移量或間接定位到目標的句柄,和虛擬機實現的內存相關,直接引用相關的目標對象必須已加載。
- 。。。
初始化:開始執行類定義中的Java程序代碼。執行類構造器<cinit>()方法,
<cinit>():
- 編譯器根據類文件中定義順序自動收集類中的類變量的賦值動作和靜態語句塊兒的語句合並產生,靜態語句塊兒只能訪問到其前定義的變量。
- 區別於類的構造方法,不需要顯示的調用父類構造器,虛擬機保證子類的<cinit>()執行之前父類的<cinit>()已經執行完成。
- 父類中的靜態語句塊兒執行於前。
- <cinit>()對於類或接口不是必須的,如果沒有變量賦值操作或靜態語句塊兒,則不生成。
- 接口的<cinit>()不需要先執行父接口的<cinit>(),同樣接口的實現類<cinit>()也不需要。
- 線程安全:虛擬機保證多線程環境中<cinit>()正確的加鎖,同步,同一時間只能有一個線程訪問初始化類的<cinit>()