作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/
1.類的載入
載入:尋找並載入類的位元據。把.class檔案的位元據讀入到記憶體中,把它存放在運行時資料區的方法區內,然後在堆區中建立一個java.lang.Class對象(這就是類載入的最終產品),用來封裝類在方法區內的資料結構,並且向JAVA程式提供了訪問類在方法區內的資料結構的介面。
2.類的驗證:
驗證:確保載入類的正確性,檢查的內容包括,類檔案的結構檢查,語義檢查,位元組碼驗證,二進位相容的驗證。
3.類的準備:
為類的靜態變數分配記憶體,並將其初始化為預設值)和解析類的位元據(把類中的符號轉換為直接引用)。
4.類的解析:
將類中的引用替換為指標。
5.類的初始化:
初始化:給類的靜態變數賦予正確的初始值,JVM只有在程式首次主動使用一個類或者介面的時候才會初始化它(所謂主動使用,建立類的執行個體,調用類的靜態方法,調用反射方法,初始化一個類的子類等都屬於這一類)。這個類還沒有被載入或串連,則先進行載入和串連,若類存在直接父類,則先初始化直接父類,接著在執行初始化語句,然後這個類的初始化才算完成。
以下是幾種不會導致類的初始化的類被動使用的情況:
a.對於final類型的靜態變數,如果在編譯的時候就可以算出變數的取值,那麼就不會導致類的初始化,而是直接在位元組流中儲存那個值,所以當訪問的時候其實就是訪問的那個值。例如:
public static final int a = 2*3;則public static final int b = (int) (Math.random()*5)就會導致類的初始化。
b.初始化一個類的時候,要求它的所有父類都已經被初始化了,但是這條規則並不適用於介面。但在初始化一個類時,並不會先初始化它所實現的介面。在初始化一個介面時,並不會先初始化它的父介面。
c.調用ClassLoader類的loadClass()方法載入一個類,並不是對類的主動使用,不會導致類的初始化。
類的生命週期:
當Sample類被載入、串連和初始化後,它的生命週期就開始了。當代表Sample類的Class對象不再被引用,即不可觸及時,Class對象就會結束生命週期,Sample類在方法區內的資料也會被卸載,從而結束Sample類的生命週期。
JVM自身的類載入器所載入的類,在JVM生命週期中始終不會被卸載。而使用者自訂的類載入器所載入的類是可以被卸載的。
作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/