java虚拟机规范(se8)——java虚拟机结构(一)

本文翻译自:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html

第二章 虚拟机结构

  本文档描述了一个抽象的虚拟机规范,并不描述某个特定的虚拟机实现。

  要正确实现一个Java虚拟机,你只需要能够读取class文件的格式并正确执行其中指定的操作。具体的实现并不是java虚拟机规范的一部分,因为它们会限制实现者的创造力。比如,运行时数据区域的内存布局,垃圾回收使用的算法,以及任何的java虚拟机指令的内部优化(如:转换为机器码)都留给实现者去决定。

  本规范中引用的所有Unicode都遵守Unicode 标准,6.0.0版本,可以从http://www.unicode.org/.获取。

2.1 class文件格式

  编译后能够被java虚拟机执行的代码使用了一个独立于硬件和操作系统的二进制格式,通常(不是必须的)存在一个文件中,就是通常所说的class文件格式。class文件格式精确的定义了类和接口的表示,包括一些如字节序(byte ordering)的细节,可能在平台相关的目标文件格式中这被认为是理所当然的。

  第四章,class文件格式给出了class文件格式的细节。

2.2 数据类型

  类似于java编程语言,java虚拟机操作两种数据类型:基本类型和引用类型(primitive types and reference types)。相应的,有两种类型的数据可以用于变量赋值、参数传递和方法返回:基本值和引用值(primitive values and reference values)。

  java虚拟机期望几乎所有的类型检查在运行前完成,通常由编译器完成,不应该在java虚拟机中完成。基本类型的值不需要特殊标记,或者特殊的方法在运行时确定他们的类型,也不需要将它们和引用类型区分开来。相反,Java虚拟机的指令集对不同的操作数使用不用的操作数指令,从而来区分其操作数类型。例如,iadd,ladd,fadd和dadd这些java虚拟机指令用来求两个数之和,它们分别指明了操作数的类型是int,long,float和double。更多的java虚拟机指令可参考2.11.1。

  Java虚拟机包含对对象的显式支持。对象是动态分配的类实例或数组。一个对象的引用可以认为是Java虚拟机的引用(reference)类型。引用(reference)的值可以被认为是指向对象的指针。可能存在多个对象的引用。对象始终通过引用(reference)类型的值来进行的值的操作,传递和检查。

2.3 基本数据类型和值

  java虚拟机支持的基本类型由数字类型,布尔类型以及returnAddress类型。

  数字类型包括整数类型和浮点数类型。

  具体的整数类型如下:

  •   byte,其值为8位有符号二进制补码整数,其默认值为零
  •   short,其值为16位有符号二进制补码整数,其默认值为零
  •   int,其值为32位有符号二进制补码整数,其默认值为零
  •   long,其值为64位有符号二进制补码整数,其默认值为零
  •   char,其值为16位无符号整数,表示基本多文本平面(Basic Multilingual Plane)中的Unicode代码点,使用UTF-16编码,其默认值为空代码点(' u0000')

  浮点型数字类型如下:

  •   fload,值为单精度浮点数集中的元素,或者(如果虚拟机支持的话)是单精度扩展指数(Float-Extended-Exponent)集合中的元素。默认值为正数零。
  •   double,取值范围是双精度浮点数集合中的元素,或者(如果虚拟机支持的话)是双精度扩展指数(Double-Extended-Exponent)集合中的元素。默认值为正数零。

  布尔类型的值取值范围是true和false,默认值是false(Java®虚拟机规范的第一版没有将布尔值视为Java虚拟机类型。但是,布尔值在Java虚拟机中的支持有限。Java®虚拟机规范的第二版通过将布尔值视为一种类型来澄清该问题。)

  returnAddress类型的值是指向Java虚拟机指令的操作码(opcodes)的指针。在基本类型中,除了returnAddress类型,其它类型都与Java编程语言类型直接相关联。

2.3.1 整数类型和值

  java虚拟机中的整型的取值范围如下:

  byte, (-27 to 27 - 1),

  short,  (-215 to 215 - 1),

  int,  (-231 to 231 - 1)

  long,(-263 to 263 - 1)

  char,(0 ~ 2^16-1)

  

 2.3.2 浮点类型和值

  浮点类型就是指 float 类型和 double 类型,它们在概念上与《IEEE Standard for Binary Floating-Point Arithmetic》(ANSI/IEEE Std. 754-1985, New York)

标准中定义的 32 位单精度和 64 位双精度 IEEE 754 格式取值和操作都是一致的。

  IEEE 754标准不仅包含了正负带符号数,还包括了正负零,正负无穷大,以及特殊的非数字值(下面简称NaN)。NaN表示某些无效操作的结果,比如0/0。

  每一个java虚拟机实现都必须支持两种标准的浮点数集:单精度浮点数集合和双精度浮点数集合。另外,java虚拟机实现也可以选择性的支持一种或者两种扩展指数集合:单精度扩展指数集合和双精度扩展指数集合(float-extended-exponent value set and the double-extended-exponent value set)。在某些情况下,可以使用这些扩展指数值集代替标准值集来表示float或double类型的值。

  任何有限非零浮点数可以表示为 s ⋅ m ⋅ 2(e − N + 1),其中s为+1或者-1,m为小于2N的正整数,e为一个介于Emin, −(2K−1−2)和 Emax, 2K−1−1之间的一个整数,N和K的取值范围取决于当前的浮点数值集合。部分浮点数使用这种规则得到的表示形式可能不是唯一的,例如在指定的数值集合内,可以存在一个数字 v,它能找到特定的 s、m 和 e 值来表示,使得其中 m 是偶数,并且 e 小于  2K-1,这样我们就能够通过把 m 的值减半再将 e 的值增加 1 来的方式得到 v 的另外一种不同的表示形式。在这些表示形式中,如果其中某种表示形式中 m 的值满足条件 m ≥ 2N-1的话,那就称这种表示为标准表示(Normalized Representation),不满足这个条件的其他表示形式就称为非标准表示(Denormalized Representation)。如果某个数值不存在任何满足 m ≥ 2N-1的表示形式,即不存在任何标准表示,那就称这个数字为非标准值(Denormalized Value)

  在两种必须支持的浮点数集和两种可选的浮点数集中,N和K(也包括Emin 和 Emax)的取值范围如下:

参数float单精度扩展指数集合double双精度扩展指数集合
N 24 24 53 53
K 8 ≥ 11 11 ≥ 15
Emax +127 ≥ +1023 +1023 ≥ +16383
Emin -126 ≤ -1022 -1022 ≤ -16382 

  当虚拟机实现一个或者都实现的扩展指数集,这里有一个和实现无关的限制参数K,见上表中的具体限制。参数K同时决定了EminEmax的范围。

  注意上表中的限制是经过设计的,从而保证每一个单精度浮点数必然是一个单精度扩展指数、双精度浮点数和双精度扩展指数。同样的,每一个双精度浮点数必然是双精度扩展指数。所以每一个扩展的指数集比对应的标准集具有更大的范围,但是会损失精度。

  单精度浮点数集中的元素可以精确的表示为IEEE 754标准中的单精度浮点格式,除了NaN(IEEE 754中描述了224-2中不同的NaN值)。双精度浮点数集中的元素可以精确的表示为IEEE 754标准中的双精度浮点格式,除了NaN(IEEE 754中描述了253-2中不同的NaN值)。注意,这里定义的单精度扩展指数和双精度扩展指数和IEEE 754中对应的单精度扩展和双精度扩展并不对应。不过除了 Class 文件格式中必要的浮点数表示描述以外,本规范并不特别要求表示浮点数值表示形式。 

  上面提到的单精度浮点数集合、单精度扩展指数集合、双精度浮点数集合和双精度扩展指数集合都并不是具体的数据类型。虚拟机实现使用一个单精度浮点数集合的元素来表示一个 float 类型的数值在所有场景中都是可行的,但是在某些特定的上下文环境中,也允许虚拟机实现使用单精度扩展指数集合的元素来代替。类似的,虚拟机实现使用一个双精度浮点数集合的元素来表示一个double 类型的数值在所有场景中都是可行的,但是在某些特定的上下文环境中,也允许虚拟机实
现使用双精度扩展指数集合的元素来代替。
  除了 NaN 以外,浮点数集合中的所有元素都是有序的。如果把它们从小到大按顺序排列好,那顺序将会是:负无穷,可数负数、正负零、可数正数、正无穷。
浮点数中,正数零和负数零是相等的,但是它们有一些操作会有区别。例如 1.0 除以 0.0 会产生正无穷大的结果,而 1.0 除以-0.0 则会产生负无穷大的结果。
NaN 是无序的,对它进行任何的数值比较和等值测试都会返回 false 的比较结果。值得一提的是,有且只有 NaN 一个数与自身比较是否数值上相等时会得到 false 的比较结果,任何数字与NaN 进行非等值比较都会返回 true。

2.3.3 returnAddress 类型和值

  returnAddress类型被java虚拟机使用在jsr,ret和jsr_w指令中。returnAddress的值是java虚拟机指令操作码的指针。和基本的数字类型不同,returnAddress在java编程语言中没有对应的类型,同时在运行的程序中无法被修改。

2.3.4 布尔类型

  尽管java虚拟机定义了boolean类型,但是仅仅提供了非常有限的支持。java虚拟机没有单独专门的指令来操作布尔值。相反,java编程语言中的表达式涉及到boolean类型的值会被编译为java虚拟机中的int类型。

  java虚拟机直接支持布尔数组。java虚拟机中的newarray指令允许创建boolean类型的数组。boolean类型数组的元素通过byte数组指令baload和bastore来访问和修改。

  java虚拟机将boolean数组元素编码成1和0分别表示true和false。java编程语言中boolean值会被编译器映射为java虚拟机中类型int,编译器必须使用相同的编码方式。

2.4 引用类型和值

  总共又三种类型的引用类型(reference):类类型(class types),数组类型(array types)以及接口类型(interface types),它们的值分别表示动态创建的类实例,数组和类实例或者数组实现的接口。

  数组类型由具有单个维度的组件类型(component type)组成(其长度不是由类型给出的)。数组的组件类型本身也可以是数组类型。但从任意一个数组开始,如果发现其组件类型也是数组类型的话,继续重复取这个数组的组件类型,这样操作不断执行,最终一定可以遇到组件类型不是数组的情况,这时就把这种类型成为数组类型的元素类型(Element Type)。数组的元素类型必须是原始类型、类类型或者接口类型之中的一种。

  引用值也可以是特殊的空引用,对无对象的引用,这里将用null表示。null引用本质上没有任何的运行时类型,但是可以转变为任意类型。引用类型的默认值时null。

  本规范没有强制将null编程成一个具体的值。

原文地址:https://www.cnblogs.com/lilinwei340/p/10461695.html