加載
把class字節(jié)碼通過classLoader加載進內(nèi)存
驗證
校驗字節(jié)流是否符合jvm規(guī)范
對于元數(shù)據(jù)的驗證,比如該類是否繼承了被final修飾的類?類中的字段是否與父類沖突?是否出現(xiàn)了不合理的重載?
對于字節(jié)碼的驗證,比如驗證語義的合理性,驗證類型轉(zhuǎn)化的合理性
對于符號引用的驗證,比如驗證符號引用中通過全限定名是否可以找到對應的類?驗證符號引號對應的變量和方法是否可以被當前類訪問?
準備
為類變量分配內(nèi)存并賦于初始值,比如8種基本類型是0,引用變量是null,常量初始值就是代碼中給定的值,如final static a = 123,那么準備階段a的初始值就是123.
解析
將符號引用替換成直接引用
符號引用:用來唯一標識變量、方法、類的相關信息
-
直接引用:一個內(nèi)存地址或者一個偏移量。比如類方法,類變量的直接引用是指向方法區(qū)的指針;而實例方法,實例變量的直接引用是從實例的頭指針算起到這個實例變量位置的偏移量。
舉個例子:
public class Demo { public static void a() {} public void b() {} } Demo d = new Demo();在解析過程中,"a"和"b"是實例d的兩個符號引用,分別標識靜態(tài)方法a和實例方法b,實例d的內(nèi)存地址是0xff101010,a、b的直接引用分別是0xff000100和1024,解析后,a、b的方法引用分別被替換成了0xff000100和(0xff101010+1024)
初始化
對類變量進行初始化,也就是對static修飾的變量和代碼塊進行初始化。
例如:
public class StaticFieldClass {
static {
System.out.println("first static block");
}
public StaticFieldClass() {
System.out.println("constructor");
}
public static void staticMethod() {
System.out.println("static method");
}
static {
System.out.println("last static block");
}
public static int value = 123;
}
public class NotInitialization {
public static void main(String[] args) {
StaticFieldClass sfc = new StaticFieldClass();
}
}
輸出是:
first static block
last static block
constructor