類加載共有以下步驟咕娄,如圖:
1.加載:
把class文件讀入虛擬機腾么,轉(zhuǎn)換成為運行時數(shù)據(jù)結(jié)構(gòu)奈梳,也就是InstanceClass,InstanceClass是C++實現(xiàn)的JVM中表示一個java Class的解虱,同時java class文件中的每個方法也會轉(zhuǎn)換為C++的Method對象.
記住:
1>.C++也是面向?qū)ο蟮娜列耄灿蓄惡蛯ο蟮母拍?/p>
2>.還有一件事就是把元信息保存到方法區(qū)里,也就是諸如方法的字節(jié)碼指令
- 驗證:
驗證的目的是為了確保Class文件的字節(jié)流中的信息不會危害到虛擬機殴泰;
文件格式驗證 :驗證字節(jié)流是否符合Class文件的規(guī)范于宙,如主次版本號是否在當(dāng)前虛擬機范圍內(nèi)浮驳,常量池中的常量是否有不被支持的類型等等;
元數(shù)據(jù)驗證 :對字節(jié)碼描述的信息進行語義分析捞魁,如這個類是否有父類至会,是否繼承了不被繼承的類等等;
字節(jié)碼驗證 :通過驗證數(shù)據(jù)流和控制流的分析谱俭,確定程序語義是否正確奉件,主要針對方法體的驗證。如:方法中的類型轉(zhuǎn)換是否正確昆著,跳轉(zhuǎn)指令是否正確等等县貌;
符號引用驗證 :為了確保解析動作能正確執(zhí)行;
- 準(zhǔn)備:
簡單理解就是給static成員分配空間凑懂,已經(jīng)賦值煤痕,注意是零值。比如int是0接谨,long是0L摆碉。
4 .解析:
符號引用替換為直接引用。就是說我要執(zhí)行一個方法疤坝,字節(jié)碼一般都是這么個格式的invokevirtual #7兆解。其中#7是常量表的第七個常量。但是這個常量只是一個字面量跑揉,實際代碼要能夠找到它要執(zhí)行的方法的地址,解析就是干這個的
- 初始化:
這個步驟才是執(zhí)行我們自己寫的代碼的階段了埠巨。如果一個類里有static成員或者static代碼塊历谍,編譯器變出來的class文件會自動多出來一個clinit方法,也就是說對于static成員的賦值是在這里做的辣垒。
初始化:在準(zhǔn)備階段已經(jīng)對類變量進行初始化了望侈,這里的初始化是執(zhí)行類構(gòu)造器<clinit>。
<clinit>()方法是編譯器自動收集類中所有類變量的賦值動作和靜態(tài)代碼塊而產(chǎn)生的方法(無論類變量和靜態(tài)代碼塊的位置是什么樣勋桶,都是先執(zhí)行類變量的賦值動作脱衙,再執(zhí)行靜態(tài)代碼塊) 這里特別需要注意的是,初始化只是執(zhí)行clinit而不是init例驹,加載class并不是創(chuàng)建一個對象