JVM、JRE 與 JDK
May 15, 2022不要只用程式語言的角度來看 Java,這只會看到冰山一角,單就 JDK 而言,就包含了 JRE 與 JVM。
JVM
Java 是個高階語言,要讓電腦執行你撰寫的程式,得透過編譯器的翻譯。不過 Java 編譯時,並不直接編譯為相依於某平台的指令序列,而是翻譯為中介格式的位元碼(Byte code)。
Java 原始碼副檔名為 *.java,經過編譯器翻譯為副檔名 *.class 的位元碼。如果想要執行位元碼檔案,目標平台必須安裝 JVM(Java Virtual Machine)。JVM 會將位元碼翻譯為相依於平台的機器碼。
不同的平台必須安裝專屬該平台的 JVM。這就好比你講中文(原始碼),Java編譯器幫你翻譯為英語(位元碼),之後這份英語文件,到各國家之後,再由當地看得懂英文的人(JVM)翻譯為當地語言(機器碼)。
JVM 擔任的職責之一就是當地翻譯員(其他還有記憶體、執行緒管理、垃圾回收等職責),將位元碼檔案翻譯為當時平台看得懂的指令序列,有了 JVM,你的 Java 程式就可以達到「編譯一次,到處到處執行」的跨平台目的。除了瞭解 JVM 具有讓 Java 程式跨平台的重要任務之外,撰寫 Java 程式時,對JVM的重要認知就是:
對 Java 程式而言,只認識一種作業系統,這個系統叫 JVM,位元碼檔案(副檔名為 .class 的檔案)就是 JVM 的可執行檔。
Java 程式理想上,並不用理會真正執行於哪個平台,只要知道如何執行於 JVM 就可以了,至於 JVM 實際上如何與底層平台作溝通,則是 JVM 自己的事!由於 JVM 實際上就相當於 Java 程式的作業系統,JVM 就負責了 Java 程式的各種資源管理。
JRE
之後會學到的第一個 Java 程式,其中會有這麼一段程式碼:
System.out.println("Hello World");
Java 是個標準,System、out、println 這些名稱,都是標準中所規範的名稱,實際上必須要有人根據標準撰寫出 System.java,編譯為 System.class,如此才能在撰寫第一個 Java 程式時,使用 System
類別上 out
物件的 println
方法。
誰來實作 System.java?誰來編譯為 .class?廠商必須根據相關的 JSR 標準文件,將標準程式庫實作出來,如此你撰寫的第一個 Java 程式,在各廠商實作的 JVM 上運行時,引用如 System 這些標準 API,你的第一個 Java 程式,才可能輕易地運行在不同的平台。
Java SE API 涵蓋了各式常用的程式庫,像是通用的群集(Collection)、輸入輸出、連線資料庫的 JDBC等,這些都是在各個 JSR 標準文件規範之中,
Java Runtime Environment 就是 Java 執行環境,簡稱 JRE,包括了 Java SE API 與 JVM。只要使用 Java SE API,在安裝有JRE的電腦上就可以直接運行,無需額外在你的程式中再包裝標準程式庫,而可以由JRE直接提供。
JDK
先前說過,要在 .java 撰寫 Java 程式語言,使用編譯器編譯為 .class 檔案,那麼像編譯器這樣的工具程式是由誰提供?答案就是 JDK,全名為Java Developer Killer!呃!不對!是 Java Development Kit!
JDK 包括了 javac
、javadoc
等工具程式,對於要開發 Java 程式的人,必須安裝的是 JDK,如此才有這些工具程式可以使用,JDK 本身包括了 JRE,如此你才能執行 Java 程式。
總結就是「JDK包括了Java程式語言、工具程式與 JRE,JRE 包括了部署技術、Java SE API 與 JVM。
撰寫 Java 程式的人才需要 JDK,如果你的程式只是想讓朋友執行呢?那他只要裝JRE就可以了,不用安裝 JDK,因為他不需要 javac
這些工具程式,但他需要 Java SE API 與 JVM。
JDK 安裝內容
那麼 JDK 中到底有哪些東西呢?假設 Oracle JDK 安裝至「C:\Program Files\Java\jdk-17\」,開啟該資料夾會發現以下內容:
無論是 Oracle JDK 或 OpenJDK,Java SE API 的實作原始碼,都可以在 lib 資料夾中 src.zip 找到,使用解壓縮軟體解開,就能看到許多資料夾,它們會對應至 Java SE 9 以後模組平臺系統劃分出來的各個模組,而在這些資料夾中會有許多 .java 原始碼檔案。
Java SE API 編譯好的 .class 檔的話,Java 模組平臺系統為了改進效能、安全與維護性,使用了模組執行時期映像(Modular Run-Time Images),又稱 JIMAGE,這會是 lib 資料夾中的 modules 檔案,其中包含了 .class 檔案的執行時期格式。
至於在編譯時期,引入新的 JMOD 格式來封裝模組,副檔名為 .jmod,這些檔案位於 JDK 資料夾中的 jmods 資料夾,每個模組對應的. jmod 中就包括了編譯完成的 .class 檔案。
在過去,JAR(Java Archive)檔案是封裝 .java 或 .class 檔案的主要格式,有許多開發工具,都能自動建立 JAR 檔案,而在文字模式下,可以使用 JDK 的 jar
工具程式來製作 JAR 檔案。
JMOD 格式可以包含比 JAR 檔案更多的資訊,像是原生指令、程式庫等,JDK 包含了 jmod
工具程式,可以用來建立 JMOD 檔案,或者從 JMOD 檔案取得封裝的內容(目前實際上只是 zip 壓縮,然而未來可能改變)。