Java虚拟机

本页使用了标题或全文手工转换,现处于中国大陆简体模式
求闻百科,共笔求闻
Java虚拟机
推出年份1994
设计公司昇阳电脑
体系结构类型堆栈结构加载/存储体系架构
字长/寄存器资料宽度32位
字节序
通用寄存器每个方法的操作数栈(至多65535个)及方法中的局部变量(至多65535个)
Java虚拟机概貌

Java虚拟机(英语:Java Virtual Machine,缩写为JVM),一种能够执行Java bytecode虚拟机器,以堆栈结构机器来进行实做。最早由昇阳电脑所研发并实现第一个实现版本,是Java平台的一部分,能够执行以Java语言写作的软件程序

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

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

技术规范

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

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

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

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

类加载器

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

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

  1. 加载:寻找并导入特定类型的二进制数据;
  2. 链接:执行验证、准备及(可选)解析操作;
    • 验证:确保导入类型的正确性。
    • 准备:为类变量分配内存并初始化内存为默认值。
    • 解析:将类型的符号引用转化为直接引用。
  3. 初始化:调用初始化类变量至正确起始值的Java代码。

通常而言,共有两种类加载器类型:引导类加载器(Bootstrap Class Loader)及用户定义类加载器(User Defined Class Loader)。

每款Java虚拟机实现均必须有加载受信类的引导类加载器。Java虚拟机技术规范不对类加载器寻找类的方式作出指定。

虚拟机架构

Java虚拟机以原始值(整数及浮点数)及引用的方式运行,其本质上是一个32位的机器。64位的longdouble类型数据被原生支持,但需要在帧的局部变量或操作数栈中占用两个存储单元(单个单元为32位)。booleanbyteshortchar均为符号扩充类型(char使用零扩展),且以32位整数的形式(与int类型相同)运作。较小的数据类型仅有少量用于加载、存储于类型转换的特定指令。boolean类型被视为8位byte值,0代表false,1代表true。(虽然《Java虚拟机规范第二版》阐明boolean被认为是一种数据类型,但除类型特征名字修饰及boolean数组类型外booleanbyte无太大区别。boolean类型的方法签名为Zbyte的类型签名为B。布尔型数组搭载数据类型boolean[],但每个元素使用8个字节,同时Java虚拟机不内置将布尔数据包装成位数组的功能,除此之外其与byte数组大同小异。在其他用途中,Java虚拟机实际上不知道boolean类型,因为用于操作布尔型数据的指令与操作byte的指令完全相同。)

Java虚拟机拥有用于存储对象及数组的垃圾回收堆。代码、常量及其他类数据均存储于“方法区”中。方法区逻辑上是堆的一部分,但虚拟机的实现可能会区分两者,从而可能不对方法区进行垃圾回收。每个Java虚拟机线程均有其自己的调用栈(Java虚拟机栈),用于存储。当调用方法时,Java虚拟机将新建一个帧;方法退出时,帧将自动消除。

每帧均提供一个“操作数栈”及一个“局部变量”数组。操作数栈用于计算操作数和接收被调用方法的返回值,而局部变量与寄存器的用途相同,也用于传递方法参数。故Java虚拟机既是堆栈机器,也是寄存器机

字节码指令

Java虚拟机拥有进行下列任务的指令集加载与存储算术类型转换创建并控制对象操作数栈管理(放入及拉出)控制转移(分支)方法调用并返回抛出异常基于监视器的并发

指令集存在的目的是为了保证二进制文件的兼容性。每个独立宿主操作系统需要对Java虚拟机及运行时环境的不同实现。这些Java虚拟机以相同方式语义解析字节码,但具体实现可能有所不同。比模拟字节码更复杂的是在兼容且高效的情况下实现必须映射至不同的宿主操作系统的Java核心API

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

Java虚拟机语言

Java虚拟机语言是指使用Java虚拟机托管的有效类文件来表示功能的任意编程语言。类文件中含有Java虚拟机指令集(Java字节码)、符号表及其他辅助信息。类文件是用于表达编译后的类及接口的二进制格式,与硬件及操作系统无关。[5]

市面上有多种Java虚拟机语言,既有移植至Java虚拟机的旧语言,也有全新的语言。JRubyJython可能为最知名的移植语言之二;除此之外,也有从零编写的全新语言,如热门的ClojureApache GroovyScalaKotlin。Java虚拟机语言的一大显著特征是都互相兼容,举例来说,Scala库可与Java程序互用,反之亦然。[6]

Java 7虚拟机在Java平台上实现了《JSR 292:动态类型语言支持》[7]。此特性由达芬奇机器项目开发完成,旨在延伸Java虚拟机的功能,进而支持除Java外的其他语言。[8][9]

语言实现

由于JVM并不是专为Java所实现的运行时,实际上只要有其他编程语言的编译器能生成正确Java bytecode文件,则这个语言也能实现在JVM上运行。

以下为原生就在JVM上实现运行的语言:

以下为实现了相应的JVM编译器的语言及其编译(解释)器,意味着下列语言可以使用基于Java开发的编译器进行编译或解释:

注释

  1. 原文:We intend that this specification should sufficiently document the Java Virtual Machine to make possible compatible clean-room implementations. Oracle provides tests that verify the proper operation of implementations of the Java Virtual Machine.
  2. 1996, possibly the first new language specifically designed to run on the JVM

参考文献

外部链接

参见