本文是對(duì)JVM執(zhí)行一個(gè)Class文件的過程的一個(gè)總結(jié)。比如,現(xiàn)在我有2個(gè)類:
1:Class Lava {
?? private int speed = 5;
?? void flow() {}
}
2:??? Class Volcano {
?? public static void main(String [] args) {
??? Lava lava =? new Lava ();
??? lava.flow()
}
}
下面就是JVM的某個(gè)實(shí)現(xiàn)執(zhí)行Class文件的一個(gè)過程:
1:JVM找到并讀入相應(yīng)的Class文件 :Volcano.class,然后把導(dǎo)入的二進(jìn)制數(shù)據(jù)中提取的類型信息保存到方法區(qū)(方法區(qū):保存類型信息的運(yùn)行時(shí)數(shù)據(jù)區(qū),也就是JVM內(nèi)存管理體系結(jié)構(gòu)的一個(gè)組成)
2:執(zhí)行保存在方法區(qū)的字節(jié)碼 (執(zhí)行main()方法的字節(jié)碼,)在執(zhí)行時(shí),持有指向Volcano類常量池的一個(gè)指針 (常量池:就是一個(gè)符號(hào)引用 如:Lava lava = new Lava()這句中的Lava就是一個(gè)符號(hào)引用)
3:JVM只在需要時(shí)才裝載類(動(dòng)態(tài)連接) 。JVM使用常量池指針找到第一項(xiàng),發(fā)現(xiàn)是"Lava"字符串,檢查方法區(qū),發(fā)現(xiàn)Lava類并未被裝載。
4:開始裝載Volcano.class,同樣,把讀入的二進(jìn)制數(shù)據(jù)中的類型信息放到方法區(qū)。
5:JVM用一個(gè)直接指向方法區(qū)Lava類數(shù)據(jù)的指針來替換常量池的第一項(xiàng),也就是原先的“Lava”字符串。 這個(gè)過程就是所謂的:“常量池解析”---符號(hào)引用替換為直接引用。
6:JVM準(zhǔn)備為新的Lava對(duì)象分配內(nèi)存。分配對(duì)象當(dāng)然需要類型信息,此時(shí),用剛才替換的那個(gè)指針,也就是替換“Lava”字符串的那個(gè)指針(此時(shí),這個(gè)指針指向方法區(qū)Lava類的數(shù)據(jù))來訪問Lava的類型信息(這個(gè)信息剛放到方法區(qū))。找出其中記錄的這樣一個(gè)信息:需要分配多少內(nèi)存。
7:確定內(nèi)存要多大以后,在堆上分配內(nèi)存,并初始化變量,包括超類的變量()。
8:把新生成的Lava對(duì)象引用壓到Java棧中。到此,完成Lava lava = new Lava(); speed初始化為0。
9:通過此時(shí)生成的Lava引用,把speed 初始化為正確的值 :5
10: 通過這個(gè)引用調(diào)用Flow()。
以上為我以一個(gè)例子來說明JVM 的一個(gè)實(shí)現(xiàn)執(zhí)行Class的流程,歡迎大家閱讀和提出意見.