首先介紹什么是類加載:
類加載就是java虛擬機將工程所需的Class文件中的二進制數(shù)據(jù)到內(nèi)存中,通過檢驗,解析,初始化等操作,將靜態(tài)的字節(jié)流轉(zhuǎn)化成方法區(qū)中動態(tài)的數(shù)據(jù)結(jié)構(gòu)。
類的加載主要分為三個過程:加載、連接(驗證、準備、解析)、初始化。
1、加載:主要是將Class文件中的二進制數(shù)據(jù)讀到內(nèi)存中去,然后將其轉(zhuǎn)化為方法區(qū)中的運行時數(shù)據(jù)(包括常量、靜態(tài)變量、靜態(tài)代碼塊),同時在堆中創(chuàng)建一個java.lang.Class對象,用于外部訪問這個Class類的入口。
2、連接:連接主要又分為三個階段,首先驗證加載的類中的內(nèi)容是否符合正確的結(jié)構(gòu)、JVM的規(guī)范,其次準備階段為類的靜態(tài)變量在方法區(qū)中分配內(nèi)存,并賦初始值0或者null(這一點有一個問題注意就是static int a = 100 和 static final int a =100是不一樣的第一個a準備階段的賦值是0,第二個a準備階段賦值是100),最后就是解析,將二進制數(shù)據(jù)中的符號引用轉(zhuǎn)化為直接引用。
3、初始化:初始化階段主要是對連接過程中的準備階段賦初始值的靜態(tài)變量賦程序設(shè)定的初值。初始化階段不是必須的,但是有幾種必須初始化類的情況:
當new一個類時、
使用getstatic或者putstatic讀取或者設(shè)置一個靜態(tài)變量時、
調(diào)用靜態(tài)方法、
對類進行反射調(diào)用時、
初始化子類時首先初始化父類、
當子類調(diào)用父類的靜態(tài)字段時只需初始化父類。
這幾種情況下必須對類進行初始化操作。
這里區(qū)分一下“符號引用”和“直接引用”:
public class Test{
? public static void main() {
? ? String s=”adc”;
? ? System.out.println(“s=”+s);
? }
}
利用這段代碼來解釋就其中的代表“符號引用”的是s,s是我們用來定義的一個String類型變量abc的符號,這個符號在java程序中就代表著abc這個String類型變量。
這段代碼經(jīng)過jvm加載后就在計算機中就不需要s來代指abc這個String變量,而是把s直接替換成abc的內(nèi)存地址。這里的內(nèi)存地址就稱之為直接引用。