Java虚拟机

**Java 虛擬機**（英語：Java Virtual Machine，縮寫：**JVM**），一種能夠執行 Java 位元組碼的虛擬機器，以堆疊結構機器來進行實做。最早由昇陽電腦所研發並實現第一個實現版本，是 Java 平臺的一部份，能夠執行以 Java 語言寫作的軟體程式。

Java 虛擬機器有自己完善的硬體架構，如處理器、堆疊、暫存器等，還具有相應的指令系統。JVM 封鎖了與具體作業系統平台相關的資訊，使得 Java 程式只需生成在 Java 虛擬機器上執行的目的碼（位元組碼），就可以在多種平台上不加修改地執行。通過對中央處理器（CPU）所執行的軟體實作，實現能執行編譯過的 Java 程式碼（Applet 與應用程式）。

作為一種程式語言的虛擬機器，實際上不只是專用於 Java 語言，只要生成的編譯檔案符合 JVM 對載入編譯檔案格式要求，任何語言都可以由 JVM 編譯執行。此外，除了甲骨文，也有其他開源或閉源的實現。

## 技術規範

據技術規範所述，Java 虛擬機器是一部抽象（虛擬）的電腦。但技術規範未定義使用的垃圾回收演算法及最佳化 Java 虛擬機器指令的內部演算法，這主要是為了不給實現者帶來過多困擾與限制。所有的 Java 程式僅可在對 Java 虛擬機器的抽象技術規範的具體實現環境中才可執行。

自 Java 平台標準版（J2SE）5.0 起，Java 虛擬機器的技術規範改為由 Java 社群流程開發制定（JSR 924）。2006 年，JSR 924 對技術規範進行了變更，支援更改類檔案格式的提議（JSR 202）。Java 虛擬機器的技術細節以藍皮書的形式發布，其前言稱：

> 我們希望這份文件中的技術規範足以打造出相容的淨室版 Java 虛擬機器實現。甲骨文公司提供用於驗證 Java 虛擬機器實現是否正常運作的測試專案。
> 
> 

甲骨文公司的一款 Java 虛擬機器名為 HotSpot；另一款自 BEA Systems 繼承而來的名為 JRockit。淨室設計版 Java 實現有 Kaffe、IBM J9 及 Skelmir's CEE-J 。甲骨文公司擁有 Java 商標權，且可能將其用於認證其他實現是否能完全匹配甲骨文的技術規範。

### 類別載入器

Java 位元組碼的組織單位之一是類。類別載入器實現必須辨識並載入任何為 Java 類別格式的檔案。任何實現也可辨識其他二進位檔案，但必須辨識類檔案。

類別載入器以下列嚴格順序執行三個基礎任務：

1. 載入：尋找並匯入特定類型的二進位資料；
2. 連結：執行驗證、準備及（可選）解析操作；
  * 驗證：確保匯入類型的正確性。
  * 準備：為類別變數分配記憶體並初始化記憶體為預設值。
  * 解析：將類型的符號參照轉化為直接參照。
3. 初始化：呼叫初始化類別變數至正確起始值的 Java 代碼。

通常而言，共有兩種類別載入器類型：引導類別載入器（Bootstrap Class Loader）及使用者定義類別載入器（User Defined Class Loader）。

每款 Java 虛擬機器實現均必須有載入受信類的引導類別載入器。Java 虛擬機器技術規範不對類別載入器尋找類的方式作出指定。

### 虛擬機器架構

Java 虛擬機器以原始值（整數及浮點數）及參照的方式執行，其本質上是一個 32 位元的機器。64 位元的 `long` 和 `double` 類型資料被原生支援，但需要在影格的局部變數或運算元棧中占用兩個儲存單元（單個單元為 32 位元）。`boolean`、`byte`、`short` 及 `char` 均為符號擴充類型（`char` 使用零擴充），且以 32 位元整數的形式（與 `int` 類型相同）運作。較小的資料類型僅有少量用於載入、儲存於類型轉換的特定指令。`boolean` 類型被視為 8 位元 `byte` 值，0 代表 `false`，1 代表 `true`。（雖然《Java 虛擬機器規範第二版》闡明 `boolean` 被認為是一種資料類型，但除類型特徵的名字修飾及 boolean 陣列類型外 `boolean` 和 `byte` 無太大區別。`boolean` 類型的方法簽章為 `Z` 而 `byte` 的類型簽章為 `B`。布林型陣列搭載資料類型 `boolean[]`，但每個元素使用 8 個位元組，同時 Java 虛擬機器不內建將布林封包裝成位陣列的功能，除此之外其與 `byte` 陣列大同小異。在其他用途中，Java 虛擬機器實際上不知道 `boolean` 類型，因為用於操作布林型資料的指令與操作 `byte` 的指令完全相同。）

Java 虛擬機器擁有用於儲存物件及陣列的垃圾回收堆。代碼、常數及其他類資料均儲存於「方法區」中。方法區邏輯上是堆的一部分，但虛擬機器的實現可能會區分兩者，從而可能不對方法區進行垃圾回收。每個 Java 虛擬機器執行緒均有其自己的呼叫棧（Java 虛擬機器棧），用於儲存影格。當呼叫方法時，Java 虛擬機器將新建一個影格；方法登出時，影格將自動消除。

每影格均提供一個「運算元棧」及一個「局部變數」陣列。運算元棧用於計算運算元和接收被呼叫方法的返回值，而局部變數與暫存器的用途相同，也用於傳遞方法參數。故 Java 虛擬機器既是堆疊機器，也是暫存器機。

### 位元組碼指令

Java 虛擬機器擁有進行下列任務的指令集：載入與儲存、算術、類型轉換、建立並控制物件、運算元棧管理（放入及拉出）、控制轉移（分支）、方法呼叫並返回、丟擲異常、基於監視器的並行。

指令集存在的目的是為了保證二進位檔案的相容性。每個獨立宿主作業系統需要對 Java 虛擬機器及執行時環境的不同實現。這些 Java 虛擬機器以相同方式語意解析位元組碼，但具體實現可能有所不同。比類比位元組碼更複雜的是在相容且高效的情況下實現必須對映至不同的宿主作業系統的 Java 核心 API。

上述指令集通過操作共同的抽象資料類型執行命令，而非以使用特定指令集架構的原生資料類型的方式執行。

### Java 虛擬機器語言

Java 虛擬機器語言是指使用 Java 虛擬機器代管的有效類檔案來表示功能的任意程式語言。類檔案中含有 Java 虛擬機器指令集（Java 位元組碼）、符號表及其他輔助資訊。類檔案是用於表達編譯後的類及介面的二進位格式，與硬體及作業系統無關。

市面上有多種 Java 虛擬機器語言，既有移植至 Java 虛擬機器的舊語言，也有全新的語言。JRuby 及 Jython 可能為最知名的移植語言之二；除此之外，也有從零編寫的全新語言，如熱門的 Clojure、Apache Groovy、Scala 及 Kotlin。Java 虛擬機器語言的一大顯著特徵是都互相容，舉例來說，Scala 庫可與 Java 程式互用，反之亦然。

Java 7 虛擬機器在 Java 平台上實現了《JSR 292：動態型別語言支援》。此特性由達文西機器專案開發完成，旨在延伸 Java 虛擬機器的功能，進而支援除 Java 外的其他語言。

## 語言實現

由於 JVM 並不是專為 Java 所實現的執行時，實際上只要有其他程式語言的編譯器能生成正確 Java bytecode 檔案，則這個語言也能實現在 JVM 上執行。

以下為原生就在 JVM 上實現執行的語言：

* BBj
* BeanShell
* Ceylon
* Clojure
* Fantom
* Groovy
* Java
* Kotlin
* MIDletPascal
* Scala
* Xtend

以下為實現了相應的 JVM 編譯器的語言及其編譯（解釋）器，意味著下列語言可以使用基於 Java 開發的編譯器進行編譯或解釋：

* Erlang：Erjang
* JavaScript：Rhino
* Pascal：Free Pascal
* PHP：Quercus
* Python：Jython
* REXX：NetRexx
* Ruby：JRuby
* Scheme：Kawa
* Tcl：Jacl

## 注釋

## 參考文獻

## 外部連結

* Java 虛擬機器下載 （頁面存檔備份，存於網際網路檔案館）

## 參見

* 虛擬機器