天天看點

JRE, JDK, JVM, JIT的差別(轉載)

[size=medium][url]http://swiftlet.net/archives/639[/url]

[b]1. 定義[/b]

JRE(Java Runtime Enviroment)是Java的運作環境。面向Java程式的使用者,而不是開發者。如果你僅下載下傳并安裝了JRE,那麼你的系統隻能運作Java程式。JRE是運作Java程式所必須環境的集合,包含JVM标準實作及 Java核心類庫。它包括Java虛拟機、Java平台核心類和支援檔案。它不包含開發工具(編譯器、調試器等)。

JDK(Java Development Kit)又稱J2SDK(Java2 Software Development Kit),是Java開發工具包,它提供了Java的開發環境(提供了編譯器javac等工具,用于将java檔案編譯為class檔案)和運作環境(提 供了JVM和Runtime輔助包,用于解析class檔案使其得到運作)。如果你下載下傳并安裝了JDK,那麼你不僅可以開發Java程式,也同時擁有了運作Java程式的平台。JDK是整個Java的核心,包括了Java運作環境(JRE),一堆Java工具tools.jar和Java标準類庫 (rt.jar)。

[b]2. 差別[/b]

JRE主要包含:java類庫的class檔案(都在lib目錄下打包成了jar)和虛拟機(jvm.dll);JDK主要包含:java類庫的 class檔案(都在lib目錄下打包成了jar)并自帶一個JRE。那麼為什麼JDK要自帶一個JRE呢?而且jdk/jre/bin下的client 和server兩個檔案夾下都包含jvm.dll(說明JDK自帶的JRE有兩個虛拟機)。

記得在環境變量path中設定jdk/bin路徑嗎?老師會告訴大家不設定的話javac和java是用不了的。确實jdk/bin目錄下包含了所有的指令。可是有沒有人想過我們用的java指令并不是jdk/bin目錄下的而是jre/bin目錄下的呢?不信可以做一個實驗,大家可以把jdk /bin目錄下的java.exe剪切到别的地方再運作java程式,發現了什麼?一切OK!(JRE中沒有javac指令,原因很簡單,它不是開發環境)那麼有人會問了?我明明沒有設定jre/bin目錄到環境變量中啊?試想一下如果java為了提供給大多數人使用,他們是不需要jdk做開發的,隻需要jre能讓java程式跑起來就可以了,那麼每個客戶還需要手動去設定環境變量多麻煩啊?是以安裝jre的時候安裝程式自動幫你把jre的java.exe添加到了系統變量中,驗證的方法很簡單,去Windows/system32下面去看看吧,發現了什麼?有一個java.exe。

[b]3. 難點[/b]

如果安裝了JDK,會發現你的電腦有兩套JRE,一套位于C:\Program Files\Java\jre6, 另外一套位于 C:\Program Files\Java\jdk1.6.0_41\jre目錄下。

JRE的地位就象一台PC機一樣,我們寫好的Win32應用程式需要作業系統幫我們運作,同樣的,我們編寫的Java程式也必須要JRE才能運作。是以當你裝完JDK後,如果分别在硬碟上的兩個不同地方安裝了兩套JRE,那麼你可以想象你的電腦有兩台虛拟的Java

PC機,都具有運作Java程式的功能。是以我們可以說,隻要你的電腦安裝了JRE,就可以正确運作Java應用程式。

1、為什麼Sun要讓JDK安裝兩套相同的JRE?

這是因為JDK裡面有很多用Java所編寫的開發工具,如javac.exe、jar.exe等,這些指令放置在 C:\Program Files\Java\jdk1.6.0_41\bin目錄裡。

因為他們是java編寫的指令,是以要依靠java的jar包,這些jar包存放在C:\Program Files\Java\jdk1.6.0_41\lib目錄裡

如果将C:\Program Files\Java\jdk1.6.0_41\lib\目錄裡面的tools.jar改名為tools1.jar,然後運作javac.exe,顯示如下結果:

Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac /Main

但是輸入 java -cp C:\Program Files\Java\jdk1.6.0_41\lib\tools1.jar com.sun.tools.javac.Main

會得到與javac.exe相同的結果。

從這裡我們可以證明javac.exe隻是一個包裝器(Wrapper),而制作的目的是為了讓開發者免于輸入太長的指命。

而且我們可以發現C:\Program Files\Java\jdk1.6.0_41\bin目錄下的程式都很小,不大于29K,從這裡我們可以得出一個結論。就是JDK裡的工具幾乎是用Java所編寫,是以也是Java應用程式,是以要使用JDK所附的工具來開發Java程式,也必須要自行附一套JRE才行,是以位于C:\Program Files\Java\jdk1.6.0_41\jre目錄下的那套JRE就是用來運作一般Java程式用的。

2、如果一台電腦安裝兩套以上的JRE,誰來決定呢?

這個重大任務就落在java.exe身上。java.exe的工作就是找到合适的JRE來運作Java程式。 java.exe依照底下的順序來查找JRE:自己的目錄下有沒有JRE;父目錄有沒有JRE;查詢系統資料庫:

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment]

是以java.exe的運作結果與你的電腦裡面哪個JRE被執行有很大的關系。(本文于2015年6月6日修訂)

[b]小提醒:此時的記憶會随着時間的推移而遺忘,溫故而知新,建議大家及時把本文收藏下來,以後慢慢回味。[/b]

[b]JRE & JVM[/b]

JVM -- java virtual machineJVM就是我們常說的java虛拟機,它是整個java實作跨平台的最核心的部分,所有的java程式會首先被編譯為.class的類檔案,這種類檔案可以在虛拟機上執行,class檔案并不直接與機器的作業系統相對應,而是經過虛拟機間接與作業系統互動,由虛拟機将程式解釋給本地系統執行,類似于C#中的CLR。

JVM不能單獨搞定class的執行,解釋class的時候JVM需要調用解釋所需要的類庫lib。在JDK下面的的jre目錄裡面有兩個檔案夾bin和lib,在這裡可以認為bin裡的就是jvm,lib中則是jvm工作所需要的類庫,而jvm和 lib和起來就稱為jre。JVM+Lib=JRE,如果講的具體點就是bin目錄下的jvm.dll檔案, jvm.dll無法單獨工作,當jvm.dll啟動後,會使用explicit的方法(就是使用Win32 API之中的LoadLibrary()與GetProcAddress()來載入輔助用的動态連結庫),而這些輔助用的動态連結庫(.dll)都必須位 于jvm.dll所在目錄的父目錄之中。是以想使用哪個JVM,隻需要設定PATH,指向JRE所在目錄下的jvm.dll。

[b]

JVM & JIT(zz)[/b]

[url]http://blogzhoubo.iteye.com/blog/1703871[/url]

首先,需要了解JVM對位元組碼的編譯技術。一個JAVA程式通過javac編譯成位元組碼以後,在執行的時候,由JVM将位元組碼編譯成本地機器碼,然後再執行。将位元組碼轉換成

機器碼,JVM有兩種利器,一種就是JIT,還有一種是轉譯器(interpreter)。

1>轉譯器

轉譯器将每個Java指令都轉譯成對等的微處理器指令,并根據轉譯後的指令先後次序依序執行,由于一個Java指令可能被轉譯成十幾或數十幾個對等的微處理器指令,這種模式執行的速度相當緩慢。

2>JIT

針對轉譯器的速度瓶頸,出現了JIT。[b]JIT針對一個具體的class進行編譯,經過編譯後的程式,被優化成相當精簡的原生型指令碼(native code)。[/b]編譯過一次,下次再執行的時候就不用再次編譯了,是以執行次數較多的代碼,采用JIT還是十分劃算的。但是,JIT也不是萬能的,比如:某些極少執行到的Java指令在編譯時所額外花費的時間可能比轉譯器在執行時的時間還長,這時候就不如直接使用轉譯器。

是以,轉譯器和JIT各有優缺點。

1>極少執行到或者執行次數較少的Java代碼,使用轉譯器更劃算。

2>重複執行或者執行次數較多的Java代碼,采用JIT更劃算。

然後,我們回到JVM遠端調試的正題。我們一般debug程式的時候,隻是關注其中的一部分代碼,而且大部分情況下是設定斷點,然後單步執行,而JIT的編譯機關是class,隻要我們執行了class裡面的代碼,JIT就會對整個class進行編譯,而我們實際執行的代碼一般都是其中的一部分代碼,是以從整個時間效率上來看,采用JIT反而更費時間。也就是說在JVM遠端調試這個事情上,禁用JIT(隻使用轉譯器,解釋一行執行一條)更合理,是以通過-Djava.compiler=NONE來禁止JIT。

此外,在程式中也可以即時地禁用和開啟JIT。

java.lang.Compiler.disable();

java.lang.Compiler.enable();