天天看點

類加載機制

類加載:

1,加載:将class位元組碼檔案加載到記憶體中,并在方法區建立一塊區域,存放了類的靜态變量,方法,字段,等所有的類運作時資料結構(除了非靜态成員變量(對象的特有屬性)不會被加載,其它的都會被加載。),然後會在堆中生成一個對應的class對象。

2,連結

1)驗證 :驗證階段用于檢驗被加載的類是否有正确的内部結構,其主要包括 檔案格式驗證,中繼資料驗證,位元組碼驗證,符号引用驗證。

2)準備:準備階段負責為類的靜态變量配置設定記憶體,并設定預設初始值。

3)解析:将class常量池中的符号引用替換為直接引用(記憶體位址)的過程

3,初始化:執行類構造器<clinit>()方法執行,此方法由編譯器自動收集靜态變量和靜态代碼塊 合并産生(執行順序 由語句在源碼檔案中出現的順序決定)。jvm會保證一個類的clinit方法在多線程下是線程安全的。

例1 :先執行 a = 200,再執行a = 100;

static int a = 200;

static{

a = 100;

}

例2 :先執行 a = 100,再執行a = 200;

擴充下: class.forname("xx") :得到的class是已經初始化完成的。

getclassloader().loadclass("xx"):得到的class是還沒有連結的,隻執行了第一步加載過程的。

會發生類初始化(不是執行個體化)的時機:

1,new 一個類

2,通路類的靜态變量(final類型的靜态變量除外) 或靜态方法

對于一個final類型的靜态變量。

如果該變量的值是一個常量,編譯器會在編譯時(類加載第二步的解析中)直接把這個變量出現的地方替換成它的值,是以即使程式使用該靜态變量,也不會導緻該類的初始化,因為直接使用這個值對應的位址了。

反之,如果final類型的靜态field的值不能在編譯時确定下來,則必須等到運作時才可以确定該變量的值,如果通過該類來通路它的靜态變量,則會導緻該類被初始化。

3,反射 class.forname("xx")

4,調用一個類時,若父類沒被加載,則會先加載其父類

5,虛拟機啟動時,先初始化main方法所在的類

類加載機制:

類加載器的任務 是根據類的全限定名來讀取此類的二進制位元組流到 jvm 中,然後轉換成一個與目标類對象的java.lang.class 對象的執行個體,在java 虛拟機提供三種類加載器,引導類加載器,擴充類加載器,系統類加載器。