Java虚拟机

Java虚拟机（Java Virtual Machine，缩写：JVM），一种能够执行Java字节码的虚拟机器，以堆叠结构机器来实作。最早由太阳微系统所研发并实现第一个实现版本，是Java平台的一部分，能够执行以Java语言写作的软件程式。

Java虚拟机有自己完善的硬件架构，如处理器、堆栈、寄存器等，还具有相应的指令系统。JVM屏蔽了与具体操作系统平台相关的信息，使得Java程序只需生成在Java虚拟机上运行的目标代码（字节码），就可以在多种平台上不加修改地运行。通过对中央处理器（CPU）所执行的软件实作，实现能执行编译过的Java程序码（Applet与应用程式）。

作为一种编程语言的虚拟机，实际上不只是专用于Java语言，只要生成的编译文件符合JVM对载入编译文件格式要求，任何语言都可以由JVM编译运行。此外，除了甲骨文公司提供的Java虚拟机，也有其他开源或闭源的实现。

## 技术规范

据技术规范所述，Java虚拟机是一部抽象（虚拟）的计算机。但技术规范未定义使用的垃圾回收算法及优化Java虚拟机指令的内部算法，这主要是为了不给实现者带来过多困扰与限制。所有的Java程序仅可在对Java虚拟机的抽象技术规范的具体实现环境中才可运行。

自Java平台标准版（J2SE）5.0起，Java虚拟机的技术规范改为由Java社区流程开发制定（JSR 924）。2006年，JSR 924对技术规范进行了变更，支持更改class (文件格式)的提议（JSR 202）。Java虚拟机的技术细节以蓝皮书的形式发布，其前言称：

我们希望这份文档中的技术规范足以打造出相兼容的净室版Java虚拟机实现。甲骨文公司提供用于验证Java虚拟机实现是否正常运作的测试项目。

甲骨文公司的一款Java虚拟机名为HotSpot；另一款自BEA Systems继承而来的名为JRockit。净室设计版Java实现有Kaffe、IBM J9及Skelmir's CEE-J。甲骨文公司拥有Java商标权，且可能将其用于认证其他实现是否能完全匹配甲骨文的技术规范。

### 类加载器

Java字节码的组织单位之一是类。类加载器实现必须识别并加载任何为Java类格式的文件。任何实现也可识别其他二进制文件，但必须识别类文件。

类加载器以下列严格顺序执行三个基础任务：

- 加载：寻找并导入特定类型的二进制数据。
- 链接：执行验证、准备及（可选）解析操作。
- 验证：确保导入类型的正确性。
- 准备：为类变量分配内存并初始化内存为默认值。
- 解析：将类型的符号引用转化为直接引用。
- 初始化：调用初始化类变量至正确起始值的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类库。

上述指令集通过操作共同的抽象数据类型执行命令，而非以使用特定指令集架构的原生数据类型的方式运行。

### 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

## 基本资料

- 设计师：太阳微系统
- 字长/暂存器资料宽度：32位
- 始创时间：1994
- 类型：堆叠结构及加载/存储体系架构
- 字节序：大
- 通用暂存器：每个方法的操作数栈（至多65535个）及方法中的局部变量（至多65535个）