【1】JDK、JRE、JVM區(qū)別與聯(lián)系
JVM :英文名稱(JAVA Virtual machine),就是我們耳熟能詳?shù)?Java 虛擬機(jī)。它只認(rèn)識(shí) xxx.class 這種類型的文件,它能夠?qū)?class 文件中的字節(jié)碼指令進(jìn)行識(shí)別并調(diào)用操作系統(tǒng)向上的 API 完成動(dòng)作。所以說(shuō),jvm 是 Java 能夠跨平臺(tái)的核心,具體的下文會(huì)詳細(xì)說(shuō)明。
JRE :英文名稱(Java Runtime Environment),我們叫它:Java 運(yùn)行時(shí)環(huán)境。它主要包含兩個(gè)部分,jvm 的標(biāo)準(zhǔn)實(shí)現(xiàn)和 Java 的一些基本類庫(kù)。它相對(duì)于 jvm 來(lái)說(shuō),多出來(lái)的是一部分的 Java 類庫(kù)。
JDK :英文名稱(Java Development Kit),Java 開(kāi)發(fā)工具包。jdk 是整個(gè) Java 開(kāi)發(fā)的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。
顯然,這三者的關(guān)系是:一層層的嵌套關(guān)系。JDK>JRE>JVM。
【2】為什么我們的電腦在裝完 jdk 后會(huì)有兩個(gè)版本的 jre?
留心的同學(xué)可能會(huì)發(fā)現(xiàn),我們的 jdk 安裝成功后,在 C:Program FilesJava 目錄會(huì)是這樣的(這里,我是裝的 jdk1.8 的版本)而 jdk 的子目錄下也存在一個(gè) jre。這兩個(gè)不同版本的 jre 相互之間有什么聯(lián)系嗎?
答案是:沒(méi)有聯(lián)系。甚至準(zhǔn)確的來(lái)說(shuō),它倆是一樣的,無(wú)論是用哪一個(gè)都是可以的。只是很多人習(xí)慣將會(huì)單獨(dú)安裝另一個(gè) jre,雖然單獨(dú)安裝的 jre 也并沒(méi)有被使用,原因可能就是剛開(kāi)始大家都不清楚 jdk 和 jre 之間的關(guān)系,所以就默認(rèn)的都安裝上了。
在 jdk 的 bin 目錄下,基本上都是一些可執(zhí)行文件,并且它們還不大。其實(shí)這些可執(zhí)行文件只是外層的一層封裝而已,這樣的目的是避免輸入的命令過(guò)長(zhǎng)。例如 javac.exe 內(nèi)部調(diào)用的其實(shí)是 JDK 中 lib 目錄中的 tools.jar 中 com.sun.tools.javac.Main 類,也就是說(shuō)這些工具只是入口而已。而實(shí)際上它們本身又都是由 Java 編寫(xiě)的,所以在 jdk 目錄下的 jre 既提供了這些工具的運(yùn)行時(shí)環(huán)境,也提供了我們編寫(xiě)完成的 Java 程序的運(yùn)行時(shí)環(huán)境。
所以,很明顯,jdk 是我們的開(kāi)發(fā)工具包,它集成了 jre ,因此我們?cè)诎惭b jdk 的時(shí)候可以選擇不再安裝 jre 而直接使用 jdk 中的 jre 運(yùn)行我們的 Java 程序。(但是大部分人都默認(rèn)將兩個(gè)都裝上了)。但是如果你的電腦不是用來(lái)開(kāi)發(fā) Java 程序的,而僅僅是用來(lái)部署和運(yùn)行 Java 程序的,那么完全可以不用安裝 jdk,只需要安裝 jre 即可。
【3】Java 為什么能跨平臺(tái),實(shí)現(xiàn)一次編寫(xiě),多處運(yùn)行?
Java 能夠跨平臺(tái)運(yùn)行的核心在于 JVM 。不是 Java 能夠跨平臺(tái),而是它的 jvm 能夠跨平臺(tái)。我們知道,不同的操作系統(tǒng)向上的 API 肯定是不同的,那么如果我們想要寫(xiě)一段代碼調(diào)用系統(tǒng)的聲音設(shè)備,就需要針對(duì)不同系統(tǒng)的 API 寫(xiě)出不同的代碼來(lái)完成動(dòng)作。
而 Java 引入了字節(jié)碼的概念,jvm 只能認(rèn)識(shí)字節(jié)碼,并將它們解釋到系統(tǒng)的 API 調(diào)用。針對(duì)不同的系統(tǒng)有不同的 jvm 實(shí)現(xiàn),有 linux 版本的 jvm 實(shí)現(xiàn),也有 windows 版本的 jvm 實(shí)現(xiàn),但是同一段代碼在編譯后的字節(jié)碼是一樣的。引用上面的例子,在 Java API 層面,我們調(diào)用系統(tǒng)聲音設(shè)備的代碼是唯一的,和系統(tǒng)無(wú)關(guān),編譯生成的字節(jié)碼也是唯一的。但是同一段字節(jié)碼,在不同的 jvm 實(shí)現(xiàn)上會(huì)映射到不同系統(tǒng)的 API 調(diào)用,從而實(shí)現(xiàn)代碼的不加修改即可跨平臺(tái)運(yùn)行。