本文翻译自: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编程成一个具体的值。

最新文章

  1. 配置php.ini实现PHP文件上传功能
  2. Linux下如何查看高CPU占用率线程
  3. 利用反射实现类通用的DAO层
  4. 奇怪吸引子---Thomas
  5. ssh scp ssh-copy-id 非22端口的操作方法
  6. access denied ("java.net.SocketPermission" "localhost:1527" "listen,resolve")
  7. Maven使用-- 编写POM
  8. 【转】准确理解CSS clear:left/right的含义及实际用途
  9. javascript 获取下一个节点
  10. uCGUI字符串显示过程分析和uCGUI字库的组建
  11. Libevent源码分析—event, event_base
  12. 《C++程序设计语言(英文第四版)》【PDF】下载
  13. 2017-06-23(chmod whoami chown)
  14. python_如何在一个for循环中迭代多个可迭代对象?
  15. [Swift]LeetCode125. 验证回文串 | Valid Palindrome
  16. 面试前必知Redis面试题—缓存雪崩+穿透+缓存与数据库双写一致问题
  17. React state状态
  18. 通过Application传递数据
  19. Gson全解析(中)-TypeAdapter的使用
  20. vue学习之webpack

热门文章

  1. Qt开发之Hello Qt及学习小技巧
  2. Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 0. 准备工作
  3. 苹果手机input框上方有一条阴影线以及input框的placeholder颜色的设置
  4. python updata与深拷贝
  5. 【CF888E】Maximum Subsequence(meet in the middle)
  6. 【CF912E】Prime Game(meet in the middle)
  7. 洛谷 P3956 棋盘 解题报告
  8. git 中断 merge
  9. 24. Swap Nodes in Pairs(M);25. Reverse Nodes in k-Group(H)
  10. lrzsz 移植到 ARM-linux 嵌入式板子上