JVM上遥、Java編譯器和Java解釋器

JVM粉楚、Java編譯器和Java解釋器

java解釋器就是把在java虛擬機上運行的目標代碼(字節(jié)碼)解釋成為具體平臺的機器碼的程序。即jdk或jre目錄下bin目錄中的java.exe文件抑党,而javac.exe是編譯器撵摆。

運行java程序的過程是先用javac編譯特铝,然后用java解釋壹瘟。而一經(jīng)編譯成功后稻轨,就可以直接用java.exe隨處解釋運行了。

JVM:JVM有自己完善的硬件架構(gòu)政冻,如處理器、堆棧(Stack)汽摹、寄存器等苦锨,還具有相應(yīng)的指令系統(tǒng)(字節(jié)碼就是一種指令格式)舟舒。JVM屏蔽了與具體操作系統(tǒng)平臺相關(guān)的信息,使得Java程序只需要生成在Java虛擬機上運行的目標代碼(字節(jié)碼)氏仗,就可以在多種平臺上不加修改地運行莺治。JVM是Java平臺無關(guān)的基礎(chǔ)谣旁。JVM負責(zé)運行字節(jié)碼:JVM把每一條要執(zhí)行的字節(jié)碼交給解釋器,翻譯成對應(yīng)的機器碼砌们,然后由解釋器執(zhí)行搁进。JVM解釋執(zhí)行字節(jié)碼文件就是JVM操作Java解釋器進行解釋執(zhí)行字節(jié)碼文件的過程饼问。

Java編譯器:將Java源文件(.java文件)編譯成字節(jié)碼文件(.class文件,是特殊的二進制文件峻堰,二進制字節(jié)碼文件)盅视,這種字節(jié)碼就是JVM的“機器語言”闹击。javac.exe可以簡單看成是Java編譯器。

Java解釋器:是JVM的一部分贺归。Java解釋器用來解釋執(zhí)行Java編譯器編譯后的程序。java.exe可以簡單看成是Java解釋器琼腔。

注意:通常情況下踱葛,一個平臺上的二進制可執(zhí)行文件不能在其他平臺上工作尸诽,因為此可執(zhí)行文件包含了對目標處理器的機器語言。而Class文件這種特殊的二進制文件洲赵,是可以運行在任何支持Java虛擬機的硬件平臺和操作系統(tǒng)上的商蕴!

維基百科定義:

JVM:一種能夠運行Java字節(jié)碼(Java bytecode)的虛擬機绪商。

字節(jié)碼:字節(jié)碼是已經(jīng)經(jīng)過編譯,但與特定機器碼無關(guān)腹殿,需要解釋器轉(zhuǎn)譯后才能成為機器碼的中間代碼锣尉。

Java字節(jié)碼:是Java虛擬機執(zhí)行的一種指令格式决采。

解釋器:是一種電腦程序树瞭,能夠把高級編程語言一行一行直接翻譯運行。解釋器不會一次把整個程序翻譯出來,只像一位“中間人”管行,每次運行程序時都要先轉(zhuǎn)成另一種語言再作運行捐顷,因此解釋器的程序運行速度比較緩慢雨效。它每翻譯一行程序敘述就立刻運行徽龟,然后再翻譯下一行据悔,再運行耘沼,如此不停地進行下去。它會先將源碼翻譯成另一種語言菠隆,以供多次運行而無需再經(jīng)編譯骇径。其制成品無需依賴編譯器而運行者春,程序運行速度比較快碧查。

即時編譯(Just-in-time compilation: JIT):又叫實時編譯、及時編譯传惠。是指一種在運行時期把字節(jié)碼編譯成原生機器碼的技術(shù)稻扬,一句一句翻譯源代碼泰佳,但是會將翻譯過的代碼緩存起來以降低性能耗損逝她。這項技術(shù)是被用來改善虛擬機的性能的。

JIT編譯器是JRE的一部分近刘。原本的Java程序都是要經(jīng)過解釋執(zhí)行的,其執(zhí)行速度肯定比可執(zhí)行的二進制字節(jié)碼程序慢介劫。為了提高執(zhí)行速度座韵,引入了JIT踢京。在運行時,JIT會把翻譯過來的機器碼保存起來翔烁,以備下次使用蹬屹。而如果JIT對每條字節(jié)碼都進行編譯白华,則會負擔(dān)過重弧腥,所以,JIT只會對經(jīng)常執(zhí)行的字節(jié)碼進行編譯虾攻,如循環(huán)霎箍,高頻度使用的方法等澡为。它會以整個方法為單位,一次性將整個方法的字節(jié)碼編譯為本地機器碼媒至,然后直接運行編譯后的機器碼顶别。

二進制文件:廣義的二進制文件即為文件,由文件在外部存儲設(shè)備的存放方式為二進制而得名拒啰。狹義的二進制文件即指除文本文件以外的文件驯绎。文本文件的格式包括:ASCII、MIME谋旦、txt条篷。

一.Java源文件的編譯骗随、下載 、解釋和執(zhí)行
  Java應(yīng)用程序的開發(fā)周期包括編譯赴叹、下載 指蚜、解釋和執(zhí)行幾個部分乞巧。Java編譯程序?qū)ava源程序翻譯為JVM可執(zhí)行的字節(jié)碼。這一編譯過程同C/C++ 的編譯有些不同摊鸡。當C編譯器編譯生成一個對象的代碼時绽媒,該代碼是為在某一特定硬件平臺運行而產(chǎn)生的。因此免猾,在編譯過程中是辕,編譯程序通過查表將所有對符號的引用轉(zhuǎn)換為特定的內(nèi)存偏移量,以保證程序運行猎提。Java編譯器卻不將對變量和方法的引用編譯為數(shù)值引用获三,也不確定程序執(zhí)行過程中的內(nèi)存布局,而是將這些符號引用信息保留在字節(jié)碼中锨苏,由解釋器在運行過程中創(chuàng)立內(nèi)存布局疙教,然后再通過查表來確定一個方法所在的地址。這樣就有效的保證了Java的可移植性和安全性伞租。
  
  運行JVM字節(jié)碼的工作是由解釋器來完成的贞谓。解釋執(zhí)行過程分三部進行:代碼的裝入、代碼的校驗和代碼的執(zhí)行葵诈。裝入代碼的工作由"類裝載器"(class loader)完成裸弦。類裝載器負責(zé)裝入運行一個程序需要的所有代碼,這也包括程序代碼中的類所繼承的類和被其調(diào)用的類作喘。當類裝載器裝入一個類時理疙,該類被放在自己的名字空間中。除了通過符號引用自己名字空間以外的類徊都,類之間沒有其他辦法可以影響其他類沪斟。在本臺計算機上的所有類都在同一地址空間內(nèi),而所有從外部引進的類暇矫,都有一個自己獨立的名字空間主之。這使得本地類通過共享相同的名字空間獲得較高的運行效率,同時又保證它們與從外部引進的類不會相互影響李根。當裝入了運行程序需要的所有類后槽奕,解釋器便可確定整個可執(zhí)行程序的內(nèi)存布局。解釋器為符號引用同特定的地址空間建立對應(yīng)關(guān)系及查詢表房轿。通過在這一階段確定代碼的內(nèi)存布局粤攒,Java很好地解決了由超類改變而使子類崩潰的問題所森,同時也防止了代碼對地址的非法訪問。
  
  隨后夯接,被裝入的代碼由字節(jié)碼校驗器進行檢查焕济。校驗器可發(fā)現(xiàn)操作數(shù)棧溢出,非法數(shù)據(jù)類型轉(zhuǎn)化等多種錯誤盔几。通過校驗后晴弃,代碼便開始執(zhí)行了。
  
  Java字節(jié)碼的執(zhí)行有兩種方式:
  1.即時編譯方式:解釋器先將字節(jié)碼編譯成機器碼逊拍,然后再執(zhí)行該機器碼上鞠。
  2.解釋執(zhí)行方式:解釋器通過每次解釋并執(zhí)行一小段代碼來完成Java字節(jié)碼程 序的所有操作。
  通常采用的是第二種方法芯丧。由于JVM規(guī)格描述具有足夠的靈活性芍阎,這使得將字節(jié)碼翻譯為機器代碼的工作具有較高的效率。對于那些對運行速度要求較高的應(yīng)用程序缨恒,解釋器可將Java字節(jié)碼即時編譯為機器碼谴咸,從而很好地保證了Java代碼的可移植性和高性能。
  
  二.JVM規(guī)格描述
  JVM的設(shè)計目標是提供一個基于抽象規(guī)格描述的計算機模型肿轨,為解釋程序開發(fā)人員提供了很好的靈活性寿冕,同時也確保Java代碼可在符合該規(guī)范的任何系統(tǒng)上運行。JVM對其實現(xiàn)的某些方面給出了具體的定義椒袍,特別是對Java可執(zhí)行代碼驼唱,即字節(jié)碼(Bytecode)的格式給出了明確的規(guī)格。這一規(guī)格包括操作碼和操作數(shù)的語法和數(shù)值驹暑、標識符的數(shù)值表示方式玫恳、以及Java類文件中的Java對象、常量緩沖池在JVM的存儲映象优俘。這些定義為JVM解釋器開發(fā)人員提供了所需的信息和開發(fā)環(huán)境京办。Java的設(shè)計者希望給開發(fā)人員以隨心所欲使用Java的自由。
  
  JVM定義了控制Java代碼解釋執(zhí)行和具體實現(xiàn)的五種規(guī)格帆焕,它們是:

JVM指令系統(tǒng)
  JVM寄存器
  JVM棧結(jié)構(gòu)
  JVM碎片回收堆
  JVM存儲區(qū)
  
  2.1JVM指令系統(tǒng)
  
  JVM指令系統(tǒng)同其他計算機的指令系統(tǒng)極其相似惭婿。Java指令也是由操作碼和操作數(shù)兩部分組成。操作碼為8位二進制數(shù)叶雹,操作數(shù)緊隨在操作碼的后面财饥,其長度根據(jù)需要而不同。操作碼用于指定一條指令操作的性質(zhì)(在這里我們采用匯編符號的形式進行說明)折晦,如iload表示從存儲器中裝入一個整數(shù)钥星,anewarray表示為一個新數(shù)組分配空間,iand表示兩個整數(shù)的" 與"满着,ret用于流程控制谦炒,表示從對某一方法的調(diào)用中返回贯莺。當長度大于8位時,操作數(shù)被分為兩個以上字節(jié)存放宁改。JVM采用了"big endian"的編碼方式來處理這種情況缕探,即高位bits存放在低字節(jié)中。這同 Motorola及其他的RISC CPU采用的編碼方式是一致的还蹲,而與Intel采用的"little endian "的編碼方式即低位bits存放在低位字節(jié)的方法不同撕蔼。
  
  Java指令系統(tǒng)是以Java語言的實現(xiàn)為目的設(shè)計的,其中包含了用于調(diào)用方法和監(jiān)視多先程系統(tǒng)的指令秽誊。Java的8位操作碼的長度使得JVM最多有256種指令,目前已使用了160多種操作碼琳骡。
  
  2.2JVM指令系統(tǒng)
  
  所有的CPU均包含用于保存系統(tǒng)狀態(tài)和處理器所需信息的寄存器組锅论。如果虛擬機定義較多的寄存器,便可以從中得到更多的信息而不必對楅购牛或內(nèi)存進行訪問最易,這有利于提高運行速度。然而炫狱,如果虛擬機中的寄存器比實際CPU的寄存器多藻懒,在實現(xiàn)虛擬機時就會占用處理器大量的時間來用常規(guī)存儲器模擬寄存器,這反而會降低虛擬機的效率视译。針對這種情況嬉荆,JVM只設(shè)置了4個最為常用的寄存器。它們是:
  pc程序計數(shù)器
  optop操作數(shù)棧頂指針
  frame當前執(zhí)行環(huán)境指針
  vars指向當前執(zhí)行環(huán)境中第一個局部變量的指針
  所有寄存器均為32位酷含。pc用于記錄程序的執(zhí)行鄙早。optop,frame和vars用于記錄指向Java棧區(qū)的指針。
  
  2.3JVM棧結(jié)構(gòu)
  
  作為基于棧結(jié)構(gòu)的計算機椅亚,Java棧是JVM存儲信息的主要方法限番。當JVM得到一個Java字節(jié)碼應(yīng)用程序后,便為該代碼中一個類的每一個方法創(chuàng)建一個椦教颍框架弥虐,以保存該方法的狀態(tài)信息。每個椕睦担框架包括以下三類信息:

局部變量
  執(zhí)行環(huán)境
  操作數(shù)棧
  
  局部變量用于存儲一個類的方法中所用到的局部變量霜瘪。vars寄存器指向該變量表中的第一個局部變量。
  執(zhí)行環(huán)境用于保存解釋器對Java字節(jié)碼進行解釋過程中所需的信息省古。它們是:上次調(diào)用的方法粥庄、局部變量指針和操作數(shù)棧的棧頂和棧底指針。執(zhí)行環(huán)境是一個執(zhí)行一個方法的控制中心豺妓。例如:如果解釋器要執(zhí)行iadd(整數(shù)加法)惜互,首先要從frame寄存器中找到當前執(zhí)行環(huán)境布讹,而后便從執(zhí)行環(huán)境中找到操作數(shù)棧,從棧頂彈出兩個整數(shù)進行加法運算训堆,最后將結(jié)果壓入棧頂描验。
  操作數(shù)棧用于存儲運算所需操作數(shù)及運算的結(jié)果。
  
  2.4JVM碎片回收堆
  
  Java類的實例所需的存儲空間是在堆上分配的坑鱼。解釋器具體承擔(dān)為類實例分配空間的工作膘流。解釋器在為一個實例分配完存儲空間后,便開始記錄對該實例所占用的內(nèi)存區(qū)域的使用鲁沥。一旦對象使用完畢呼股,便將其回收到堆中。
  在Java語言中画恰,除了new語句外沒有其他方法為一對象申請和釋放內(nèi)存彭谁。對內(nèi)存進行釋放和回收的工作是由Java運行系統(tǒng)承擔(dān)的。這允許Java運行系統(tǒng)的設(shè)計者自己決定碎片回收的方法允扇。在SUN公司開發(fā)的Java解釋器和Hot Java環(huán)境中缠局,碎片回收用后臺線程的方式來執(zhí)行。這不但為運行系統(tǒng)提供了良好的性能考润,而且使程序設(shè)計人員擺脫了自己控制內(nèi)存使用的風(fēng)險狭园。
  
  2.5JVM存儲區(qū)
  
  JVM有兩類存儲區(qū):常量緩沖池和方法區(qū)。常量緩沖池用于存儲類名稱糊治、方法和字段名稱以及串常量唱矛。方法區(qū)則用于存儲Java方法的字節(jié)碼。對于這兩種存儲區(qū)域具體實現(xiàn)方式在JVM規(guī)格中沒有明確規(guī)定俊戳。這使得Java應(yīng)用程序的存儲布局必須在運行過程中確定揖赴,依賴于具體平臺的實現(xiàn)方式。
  
  JVM是為Java字節(jié)碼定義的一種獨立于具體平臺的規(guī)格描述抑胎,是Java平臺獨立性的基礎(chǔ)燥滑。目前的JVM還存在一些限制和不足,有待于進一步的完善阿逃,但無論如何铭拧,JVM的思想是成功的。
  
  對比分析:如果把Java源程序想象成我們的C++源程序恃锉,Java源程序編譯后生成的字節(jié)碼就相當于C++源程序編譯后的80x86的機器碼(二進制程序文件)搀菩,JVM虛擬機相當于80x86計算機系統(tǒng),Java解釋器相當于80x86CPU破托。在80x86CPU上運行的是機器碼肪跋,在Java解釋器上運行的是Java字節(jié)碼。
  
   Java解釋器相當于運行Java字節(jié)碼的“CPU”土砂,但該“CPU”不是通過硬件實現(xiàn)的州既,而是用軟件實現(xiàn)的谜洽。Java解釋器實際上就是特定的平臺下的一個應(yīng)用程序。只要實現(xiàn)了特定平臺下的解釋器程序吴叶,Java字節(jié)碼就能通過解釋器程序在該平臺下運行阐虚,這是Java跨平臺的根本。當前蚌卤,并不是在所有的平臺下都有相應(yīng)Java解釋器程序实束,這也是Java并不能在所有的平臺下都能運行的原因,它只能在已實現(xiàn)了Java解釋器程序的平臺下運行逊彭。

推薦書籍:《深入理解計算機系統(tǒng)》《深入java虛擬機》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咸灿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子侮叮,更是在濱河造成了極大的恐慌析显,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件签赃,死亡現(xiàn)場離奇詭異,居然都是意外死亡分尸,警方通過查閱死者的電腦和手機锦聊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來箩绍,“玉大人孔庭,你說我怎么就攤上這事〔闹耄” “怎么了圆到?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長卑吭。 經(jīng)常有香客問我芽淡,道長,這世上最難降的妖魔是什么豆赏? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任挣菲,我火速辦了婚禮,結(jié)果婚禮上掷邦,老公的妹妹穿的比我還像新娘白胀。我一直安慰自己,他們只是感情好抚岗,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布或杠。 她就那樣靜靜地躺著,像睡著了一般宣蔚。 火紅的嫁衣襯著肌膚如雪向抢。 梳的紋絲不亂的頭發(fā)上认境,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機與錄音笋额,去河邊找鬼元暴。 笑死,一個胖子當著我的面吹牛兄猩,可吹牛的內(nèi)容都是我干的茉盏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼枢冤,長吁一口氣:“原來是場噩夢啊……” “哼鸠姨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起淹真,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤讶迁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后核蘸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巍糯,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年客扎,在試婚紗的時候發(fā)現(xiàn)自己被綠了祟峦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡徙鱼,死狀恐怖宅楞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情袱吆,我是刑警寧澤厌衙,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站绞绒,受9級特大地震影響婶希,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蓬衡,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一饲趋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧撤蟆,春花似錦奕塑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春换棚,著一層夾襖步出監(jiān)牢的瞬間式镐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工固蚤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留娘汞,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓夕玩,卻偏偏與公主長得像你弦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子燎孟,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理禽作,因此不免有一些不準確的地方,同時不同JDK版本的...
    高廣超閱讀 15,599評論 3 83
  • 每個使用Java的開發(fā)者都知道Java字節(jié)碼是在JRE中運行(JRE: Java 運行時環(huán)境)揩页。JVM則是JRE中...
    燕京博士閱讀 1,406評論 0 6
  • 1 今天我和廣州的老同學(xué)電話聯(lián)系旷偿,聊了一些近況,多年不見的老同學(xué)在聊天時爆侣,仍然感覺很親切萍程,內(nèi)心洋溢著高中時的快樂時...
    LiHongxi閱讀 163評論 0 0
  • 星空 人間滿是淚 無奈望星空 多情獨倚空自悔 意闌風(fēng)靜 寸心常念遠 窗前糝糝黑影 月半和衣睡 從來孑然一身、踽踽獨...
    pikachuka閱讀 160評論 0 1
  • 問題① CocoaPods did not set the base configuration of your ...
    莫_名閱讀 177評論 0 0