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