第1章 Java的開發(fā)運(yùn)行環(huán)境
學(xué)好Java最重要的一個(gè)步驟就是上機(jī)編程,熟悉Java的開發(fā)運(yùn)行環(huán)境是成為Java程序員的第一步。本章將詳細(xì)介紹如何安裝并配置好Sun公司提供的JDK1.5 for Windows,如何編制一個(gè)簡單的Java程序,如何編譯一個(gè)Java源程序,如何運(yùn)行編譯好的class文件以及如何避免初學(xué)者常犯的錯(cuò)誤。通過本章的學(xué)習(xí),將輕松地邁入Java的殿堂。
1.1 Java的運(yùn)行環(huán)境與虛擬機(jī)
任何一個(gè)可執(zhí)行文件,都必須在某個(gè)平臺(tái)上才能運(yùn)行。例如,Windows下的exe文件,必須在Windows環(huán)境下、X86硬件平臺(tái)上才能運(yùn)行。這些exe文件,通常是使用C/C++、Pascal或VB等語言編程,然后通過編譯、鏈接而形成的。在這些可執(zhí)行文件中,包含了運(yùn)行它的硬件平臺(tái)的相關(guān)信息,所以如果要把它移植到其他平臺(tái)上,必須要重新編譯,甚至要修改源文件。
Java和這些語言不同,它的最大特點(diǎn)就是平臺(tái)無關(guān)性。Java文件經(jīng)編譯后,生成的是一個(gè)后綴名為class的文件。這是一種字節(jié)碼文件,它不像普通可執(zhí)行文件那樣包含硬件信息,而是完全與硬件平臺(tái)無關(guān),也就是無法直接由操作系統(tǒng)調(diào)用運(yùn)行。所以Java的應(yīng)用程序,需要一個(gè)更為復(fù)雜的平臺(tái)才能運(yùn)行。這個(gè)運(yùn)行平臺(tái),包括計(jì)算機(jī)操作系統(tǒng)、適配器、Java虛擬機(jī)、Java基本軟件和Java應(yīng)用程序接口,它們負(fù)責(zé)將Java的字節(jié)碼翻譯成硬件可以接受的指令。整個(gè)運(yùn)行系統(tǒng)的結(jié)構(gòu)如圖1.1所示。
圖1.1 Java運(yùn)行系統(tǒng)
Java運(yùn)行系統(tǒng)執(zhí)行Java應(yīng)用程序的過程包括三個(gè)步驟:首先是代碼的裝入,然后是代碼的驗(yàn)證,最后是代碼的執(zhí)行。
代碼的裝入由類裝配器完成,它主要負(fù)責(zé)裝入程序運(yùn)行時(shí)所需要的全部代碼,包括程序運(yùn)行中調(diào)用到的其他類。當(dāng)類裝配器裝入一個(gè)類后,該類被放在自己的命名空間中,除了通過符號(hào)引用其他類之外,該類不能影響其他類所在的空間。當(dāng)裝入了運(yùn)行程序所需要的所有類后,運(yùn)行系統(tǒng)就能確定整個(gè)可執(zhí)行程序的內(nèi)存布局。
然后,被裝入的代碼將由字節(jié)碼驗(yàn)證器進(jìn)行安全檢查,以確保字節(jié)代碼不存在違反訪問權(quán)限、不規(guī)范的數(shù)據(jù)類型和非法調(diào)用等問題。
通過校驗(yàn)之后,代碼就可以運(yùn)行了。Java的字節(jié)碼有兩種運(yùn)行方式:
? 解釋執(zhí)行方式:通過“解釋器”,將字節(jié)碼翻譯成機(jī)器碼,然后由“運(yùn)行支持庫”將機(jī)器碼送往硬件執(zhí)行。整個(gè)執(zhí)行過程是一邊翻譯一邊執(zhí)行,稱為解釋執(zhí)行。Java系統(tǒng)一般采用這種方式。
? 即時(shí)編譯方式:通過“代碼生成器”,先一次性地將所有字節(jié)碼翻譯成適用于特定計(jì)算機(jī)系統(tǒng)的機(jī)器碼,然后送往硬件執(zhí)行。對(duì)程序運(yùn)行速度要求較高時(shí),一般采用這種方式。
從圖1.1可以看出,Java的字節(jié)碼并沒有直接運(yùn)行在硬件平臺(tái)上,而是在一個(gè)虛擬的軟件平臺(tái)上運(yùn)行。這個(gè)虛擬的軟件平臺(tái),被稱為Java虛擬機(jī)(Java Virtual Machine,JVM)。為了讓編譯產(chǎn)生的字節(jié)碼可以更好地解釋與執(zhí)行,通常把JVM分成6個(gè)功能模塊:JVM解釋器、指令系統(tǒng)、寄存器、棧、存儲(chǔ)區(qū)和碎片回收區(qū)。
? JVM解釋器:JVM解釋器負(fù)責(zé)將字節(jié)碼轉(zhuǎn)換成為CPU能執(zhí)行的機(jī)器指令。
? 指令系統(tǒng):指令系統(tǒng)同硬件計(jì)算機(jī)很相似。一條指令分成操作碼和操作數(shù)兩部分。操作碼為8位二進(jìn)制數(shù),操作數(shù)可以根據(jù)需要而定。操作碼是為了說明一條指令的功能,所以JVM可以有多達(dá)256種不同的操作指令。
? 寄存器:JVM有自己的虛擬寄存器,這樣就可以快速地和JVM的解釋器進(jìn)行數(shù)據(jù)交換。為了實(shí)現(xiàn)必需的功能,JVM設(shè)置了4個(gè)常用的32位寄存器:pc(程序計(jì)數(shù)器)、optop(操作數(shù)棧頂指針)、frame(當(dāng)前執(zhí)行環(huán)境指針)和vars(指向當(dāng)前執(zhí)行環(huán)境中第一個(gè)局部變量的指針)。
? 棧:JVM棧是指令執(zhí)行時(shí)數(shù)據(jù)和信息存儲(chǔ)的場(chǎng)所和控制中心,它提供給JVM解釋器運(yùn)算時(shí)所需要的信息。
? 存儲(chǔ)區(qū):JVM存儲(chǔ)區(qū)用于存儲(chǔ)編譯后的字節(jié)碼等信息。
? 碎片回收區(qū):JVM碎片回收,是指將那些使用后的Java類的具體實(shí)例從內(nèi)存中進(jìn)行回收。因此,可以避免開發(fā)人員自己編程控制內(nèi)存的麻煩。隨著JVM的不斷升級(jí),其碎片回收技術(shù)和算法也更加合理。比較經(jīng)典的算法有引用計(jì)數(shù)、復(fù)制、標(biāo)記-清除和標(biāo)記-整理。在JVM 1.4.1版以后,產(chǎn)生了一種代收集技術(shù)。簡單地說,就是利用對(duì)象在程序中生存的時(shí)間劃分成代,以這個(gè)代為標(biāo)準(zhǔn)進(jìn)行碎片回收。
?說明:JVM的運(yùn)用,真正讓Java實(shí)現(xiàn)了“一次編譯,處處運(yùn)行”,它是整個(gè)運(yùn)行系統(tǒng)的核心