JVM對類的加載、連接、初始化總結

類加載:
在Java代碼中,類型的加載、連接與初始化過程都是在程序運行期間完成的。提供了更大靈活性的同時,也增加了更多的可能性。

  • 加載:把二進制形式的Java類型讀入java虛擬機中
  • 連接
    驗證:確保被加載類的正確性
    準備:爲類的靜態變量分配內存,並將其初始化爲默認值。在到達初始化之前,類變量都沒有初始化爲真正的初始值
    解析:解釋過程就是在類型的常量池中尋找類、接口、字段和方法的符號引用,把這些符合引用替換成直接引用
  • 初始化:爲類的靜態變量賦予正確的初始值,每個類只會被初始化一次
  • 使用(實例化)
    爲新的對象分配內存;爲實例變量賦默認值;爲實例變量賦正確的初始值;java編譯器爲它編譯的每一個類都至少生成一個實例初始化方法,在java的class文件中,這個實例化初始化方法稱爲。針對源代碼中的每一個類的構造法方法,java編譯器都產生一個方法
  • 垃圾回收和對象終結(卸載)

java程序對類的使用方式可分爲兩種
主動使用、被動使用
所用的java虛擬機實現必須在每個類或接口被java程序首次主動使用時,才初始化他們
主動使用(七種)

  1. 創建類的實例
  2. 訪問某個類或者接口的靜態變量,或者對該靜態變量賦值
  3. 調用類的靜態方法
  4. 反射(如Class.forName(“XXX.XXX”))
  5. 初始化一個類的子類
  6. Java虛擬機啓動時被標明爲啓動類的類(Java Test)
  7. JDK1.7開始提供的動態語言支持:java.lang.invoke.MethodHandle實例的解析結果REF_getStatic.RF_putStatic,REF_invokeStatic句柄對應的類沒有初始化,則進行初始化
    除了以上七種情況,其他使用java類的方式都被看作是對類的被動使用,都不會導致類的初始化
/**
* 案例:驗證初始化順序
* 代碼在1處未註釋,輸出1,1
* 代碼在2處未註釋時,輸出1,0
* 原因代碼初始化的順序是按照代碼在類中從上到下的順序進行賦值,所以情況2輸出j的結果
* 爲重新賦值
*/
public class Test1 {

    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println(Singleton.i);
        System.out.println(Singleton.j);
    }
}

class Singleton {
    public static int i;
    //1.
    public static int j = 0;

    private static Singleton singleton = new Singleton();
    public Singleton() {
        i++;
        j++;
    }
    //2.
//    public static int j = 0;

    public static Singleton getInstance() {
        return singleton;
    }

}

發佈了106 篇原創文章 · 獲贊 69 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章