扣丁學(xué)堂給你Java 虛擬機(jī) ( JVM ) 概述
2018-08-10 09:18:01
1227瀏覽
JVM(Java虛擬機(jī))是一個抽象的計算模型。就如同一臺真實的機(jī)器,它有自己的指令集和執(zhí)行引擎,可以在運行時操控內(nèi)存區(qū)域。目的是為構(gòu)建在其上運行的應(yīng)用程序提供一個運行環(huán)境。JVM可以解讀指令代碼并與底層進(jìn)行交互:包括操作系統(tǒng)平臺和執(zhí)行指令并管理資源的硬件體系結(jié)構(gòu)。本文主要對JVM進(jìn)行概述,并介紹Java程序是如何在上面執(zhí)行的。這樣子可以給參加JAVA培訓(xùn)的同學(xué)一點干貨。
虛擬機(jī)
從本質(zhì)上講,虛擬機(jī)是個被構(gòu)建來提供特定或通用目的服務(wù)環(huán)境的非實體計算機(jī)。這聽起來像是一個仿真器,用來仿真機(jī)器未配置或不能按要求執(zhí)行任務(wù)的硬件組件。因此,我們要做的就是創(chuàng)建一個軟件,以軟件的形式模擬硬件提供的服務(wù),使之看起來這個特定的硬件在系統(tǒng)中是實際存在的。虛擬機(jī)在一定程度上使用CPU虛擬化,為實際的硬件問題提供一個接口。所以可以說它實際上有兩種功能:提供一個虛擬的環(huán)境,或者將某些不存在的事物進(jìn)行抽象化。但是當(dāng)我們深入了解之后會發(fā)現(xiàn),這兩種功能有著很明顯的不同。我們現(xiàn)在暫且不看它們之間的不同點,它們的共同點在于都“假裝”成它們不是的東西。正如Popek和Goldberg在論文“FormalRequirementsforVirtualizableThirdGenerationArchitectures”里說的,它是“一個真實機(jī)器有效、獨立的復(fù)制品?!?br />
基于不同的需求和用途,虛擬機(jī)有很多類型。一種叫完全虛擬化(fullvirtualization),這種虛擬機(jī)表現(xiàn)得像一臺真正的機(jī)器。其他類型的虛擬機(jī)會更精細(xì),更專業(yè),比如進(jìn)程虛擬化(processvirtualization)。而對JVM進(jìn)行分類是很困難的,因為它對CPU進(jìn)行了虛擬化,有自己的運行時環(huán)境、與底層平臺協(xié)調(diào)工作的內(nèi)存管理器、垃圾收集器,當(dāng)然還有大量作為中間字節(jié)碼輸入的類庫,最后但同樣重要的是,它能夠模擬機(jī)器的寄存器、堆棧等等。簡單地說,它是被Java編譯器編譯為java的本質(zhì)——字節(jié)碼的游樂場。字節(jié)碼實際上是JVM用來將代碼重新翻譯為本地機(jī)器指令所使用的機(jī)器代碼。
類文件格式
有趣的是,其實JVM并不關(guān)心Java語言或其他編程語言的語義和語法結(jié)構(gòu)。當(dāng)JVM執(zhí)行一段程序的時候,它主要關(guān)注的是一種稱為“類文件”的特定文件格式。*.class類文件格式和Java代碼定義的面向?qū)ο蟮念惤Y(jié)構(gòu)毫無關(guān)系。編譯器將*.java文件編譯成*.class文件,然后JVM對*.class文件進(jìn)行解譯,它不關(guān)心這個類文件是由哪種編譯器生成的,只要符合類文件的文件格式即可。Java編譯器將一段程序編譯為等價的類文件。這些類文件實際上包含了半編譯的代碼——字節(jié)碼。之所以稱之為半編譯,是因為字節(jié)碼并不像C/C++編譯器編譯的二進(jìn)制文件一樣會被直接執(zhí)行。字節(jié)碼要先被輸入到JVM中,然后再轉(zhuǎn)換為底層平臺可以執(zhí)行的最終指令。所以字節(jié)碼包含了JVM的指令、符號表和其他的輔助信息。不管何種語言,能根據(jù)JVM的語法和結(jié)構(gòu)約束編譯生成字節(jié)碼的編譯器,都是一個可以在JVM上執(zhí)行的候選者。
JVM的定位
JVM將自身定位于字節(jié)碼和底層平臺之間。底層平臺是指操作系統(tǒng)(OS)和硬件。操作系統(tǒng)和硬件體系結(jié)構(gòu)在不同的機(jī)器上可能不同,但是同一段Java程序可以不用做任何的代碼修改就能在不同的機(jī)器上運行。這是在虛擬環(huán)境中執(zhí)行的程序語言的獨特之處。例如,由其他程序語言編譯器編譯的目標(biāo)代碼如C++和Java相比的不同點在于,C++程序需要被特定平臺的編譯器重新編譯,從而使它能在不同的體系結(jié)構(gòu)上面運行。而Java代碼并不需要做任何改變,因為由Java編譯器編譯的字節(jié)碼是在外圍的JVM上執(zhí)行。因此,JVM負(fù)責(zé)重新解譯由Java編譯器生成的字節(jié)碼,并和底層平臺協(xié)調(diào)工作。也就是說,盡管Java編譯器生成的結(jié)果是平臺獨立的,但JVM與特定平臺相關(guān)的。除非兩臺機(jī)器有相同的體系結(jié)構(gòu),在某個體系結(jié)構(gòu)上安裝和使用的JVM可能換一臺機(jī)器就不能正常工作了。
1
相對于JVM,JRE和JDK又是什么?
想要運行Java程序,我們需要JVM因為它提供了字節(jié)碼的運行環(huán)境。Oracle提供了兩種不同的產(chǎn)品:JDK(Java開發(fā)工具)和JRE(Java運行環(huán)境)。JRE是我們安裝運行Java程序的最基本軟件。它和Java類庫以及運行Java程序所需要的其他組件一起夠成了JVM的一個實現(xiàn)。所以,如果我們想運行一個類文件或一段字節(jié)碼,僅需要JRE就夠了。而JDK(Java開發(fā)工具)是JRE的超集。它包含了JRE提供的所有東西,包括創(chuàng)建類文件的工具如Java編譯器、調(diào)試器和其他許多開發(fā)Java程序相關(guān)的工具。所以,當(dāng)我們要創(chuàng)建類文件(編譯Java源碼)時,我們就需要JDK。下面是一張JavaAPI文檔的截圖。注意組成JDK,JRE和JavaSEAPI核心類庫的組件;通過這張截圖你可以了解JRE和JDK里面都有哪些內(nèi)容。
2
Java提供了Java虛擬機(jī)規(guī)范來讓我們對JVM的工作原理有一個完整的認(rèn)識。你可以從這里得到概念性知識,并開發(fā)一個自己的JVM;但這并不是一個簡單的工作?,F(xiàn)在市場上已經(jīng)有很多JVM了,其中有些是免費的,還有一些需要購買商業(yè)許可證才能使用。
在JVM上執(zhí)行Java程序
每一個在JRE上運行的Java程序都會創(chuàng)建一個JVM實例。編譯后的Java類文件和其他被依賴的類文件會被加載到運行環(huán)境中。這一步由類加載器協(xié)助完成。
3
類加載器通過三步完成類加載。
首先,類加載器會以字節(jié)碼的形式加載程序類文件和與JDK綁定的標(biāo)準(zhǔn)Java類文件。標(biāo)準(zhǔn)類文件構(gòu)成了JavaAPI核心類庫。引導(dǎo)程序通過定位通常位于jre/lib目錄下的核心API類庫啟動。
然后,擴(kuò)展機(jī)制定位擴(kuò)展類庫,例如一些為開發(fā)或執(zhí)行代碼而被添加到Java里新的(可選)包。擴(kuò)展類通常位于jre/lib/ext目錄下。有時,擴(kuò)展類會被放到系統(tǒng)屬性java.ext.dirs定義的其他目錄下面。程序包使用JAR或ZIP的擴(kuò)展名。
最后,如果要加載的類沒有在Java的標(biāo)準(zhǔn)類庫或擴(kuò)展類庫中被找到,加載器會搜索CLASSPATH環(huán)境變量下定義的文件路徑,CLASSPATH里面包含了諸多存儲類文件的地址。系統(tǒng)屬性java.class.path對CLASSPATH環(huán)境變量做了映射。
像JAR或ZIP這樣的歸檔文件都是包含了一些其他文件目錄的獨立文件,通常是壓縮文件格式。例如,程序中使用的標(biāo)準(zhǔn)類庫包含在歸檔文件rt.jar中,該文件會和JDK被一同安裝。
一旦文件被定位并加載之后,類加載器會執(zhí)行不同的功能,例如根據(jù)JVM的約束進(jìn)行校驗、內(nèi)存分配,或者在調(diào)用構(gòu)造器設(shè)置定義的變量元素之前使用默認(rèn)值初始化類變量。
當(dāng)加載程序結(jié)束之后,字節(jié)碼指令被傳遞給執(zhí)行引擎。然后JVM借助于綁定到指定平臺的特定JVM實現(xiàn)的本地代碼和底層操作系統(tǒng)進(jìn)行交互。請注意,不同平臺的實現(xiàn)可能有略微不同。
數(shù)據(jù)存儲區(qū)的堆空間用于存儲動態(tài)或臨時分配的內(nèi)存空間。類和數(shù)組是在這塊區(qū)域里創(chuàng)建的。當(dāng)創(chuàng)建對象大小超出堆內(nèi)存空間時,垃圾收集器會回收內(nèi)存。
Java棧,又叫棧幀,用于存儲局部變量和不同階段方法調(diào)用的臨時結(jié)果。每一次方法調(diào)用都會創(chuàng)建一個棧幀。
方法區(qū)基本上是JVM線程間的共享存儲區(qū)。
寄存器是一個模擬的底層機(jī)器寄存器,主要用于執(zhí)行字節(jié)碼指令。PC寄存器或程序計數(shù)器是用于保存當(dāng)前指令執(zhí)行地址的主要寄存器。
JVM功能概述
JVM的功能可以歸納為:
加載:通過類加載器加載類文件的過程。
鏈接:鏈接類文件,提交給JVM在運行時執(zhí)行。
初始化:分配內(nèi)存和調(diào)用類初始化方法設(shè)置變量值。
總結(jié)
使用虛擬機(jī)執(zhí)行程序的最大好處是它是平臺獨立的。和C/C++這種高效的語言相比,這種類型編程語言的生產(chǎn)力可以彌補(bǔ)其性能上的弱點。本文僅僅是對JVM的一點淺見,但也許已經(jīng)足以幫助理解JVM是如何實際工作的。
以上就是扣丁學(xué)堂Java在線學(xué)習(xí)小編給大家分享的
文章,希望對小伙伴們有所幫助,想要了解更多關(guān)于Java開發(fā)內(nèi)容的小伙伴可以登錄扣丁學(xué)堂官網(wǎng)咨詢,扣丁學(xué)堂有專業(yè)的Java培訓(xùn)班邀請有理想的你加入??鄱W(xué)堂不僅有專業(yè)的Java培訓(xùn)班供大家學(xué)習(xí),還有與時俱進(jìn)的課程體系和大量的J
ava在線視頻教程讓學(xué)員免費觀看學(xué)習(xí),想要學(xué)好Java開發(fā)的小伙伴快到扣丁學(xué)堂來了解詳情吧??鄱W(xué)堂Java技術(shù)交流群:670348138。
【關(guān)注微信公眾號獲取更多學(xué)習(xí)資料】
查看更多關(guān)于“Java開發(fā)資訊”的相關(guān)文章>>
標(biāo)簽:
Java培訓(xùn)
Java視頻教程
Java在線視頻
Lambda表達(dá)式之集合操作