Java:類加載程序

1.加載——3件事
- 1.通過全類名獲取定義此類的二進制位元組流(eg:從jar、war中獲取);
- 2.將位元組流所代表的靜態存盤結構轉換為方法區的運行時資料結構;
- 3.在記憶體中生成一個代表該類的Class物件,作為方法區這些資料的訪問入口,
2.連接
加載階段和連接階段的部分內容是交叉進行的,加載尚未結束,連接階段可能就開始運行了,
2.1.驗證

2.2.準備
準備階段:正式為類變數分配記憶體并設定類變數初始值的階段,這些記憶體在方法區分配,注意:
- 1.這時候進行記憶體分配的僅包括類變數(static),而不包括實體變數,實體變數會在物件實體化時隨著物件一塊分配在 Java 堆中;
- 2.除了含有final修飾的變數外,其他都賦值0,null,false這種的,
如下例子, value 的值就被復制為 111,而不是0.
public static final int value=111
2.3.決議
決議階段是虛擬機將常量池中的符號參考替換為直接參考的程序,
- 也就是得到類或者欄位、方法在記憶體中的指標或者偏移量,
什么是符號參考?
* 比如org.simple.People類參考了org.simple.Language類;
* 在編譯時People類并不知道Language類的實際記憶體地址,因此只能使用符號org.simple.Language
3.初始化
初始化是類加載的最后一步,也是真正執行類中定義的 Java 程式代碼(位元組碼),初始化階段是執行類構造器 < clinit >() 方法的程序,
對于< clinit >() 方法的呼叫,虛擬機會自己確保其在多執行緒環境中的安全性,因為 < clinit >() 方法是帶鎖執行緒安全,所以在多執行緒環境下進行類初始化的話可能會引起死鎖,并且這種死鎖很難被發現,
對于初始化階段,虛擬機嚴格規范了有且只有5中情況下,必須對類進行初始化:
- 1.當遇到 new 、 getstatic、putstatic或invokestatic 這4條直接碼指令時,比如 new 一個類,讀取一個靜態欄位(未被 final 修飾)、或呼叫一個類的靜態方法時,
- 2.使用 java.lang.reflect 包的方法對類進行反射呼叫時 ,如果類沒初始化,需要觸發其初始化.
- 3.初始化一個類,如果其父類還未初始化,則先觸發該父類的初始化,
- 4.當虛擬機啟動時,用戶需要定義一個要執行的主類 (包含 main 方法的那個類),虛擬機會先初始化這個類,
- 5.當使用 JDK1.7 的動態動態語言時,如果一個 MethodHandle 實體的最后決議結構為 REF_getStatic、REF_putStatic、REF_invokeStatic、的方法句柄,并且這個句柄沒有初始化,則需要先觸發器初始化,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/297972.html
標籤:其他
