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同时决定了Emin和Emax的范围。
注意上表中的限制是经过设计的,从而保证每一个单精度浮点数必然是一个单精度扩展指数、双精度浮点数和双精度扩展指数。同样的,每一个双精度浮点数必然是双精度扩展指数。所以每一个扩展的指数集比对应的标准集具有更大的范围,但是会损失精度。
单精度浮点数集中的元素可以精确的表示为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编程成一个具体的值。
java虚拟机规范(se8)——java虚拟机结构(一)的更多相关文章
- java虚拟机规范(se8)——java虚拟机结构(二)
2.5 运行时数据区域 java虚拟机定义了多个用于程序执行期间的运行时数据区域.这些数据区域中一些随着java虚拟机的启动而创建,随着虚拟机的退出而销毁.其他的数据区域时和线程相关的.线程相关数据区 ...
- java虚拟机规范(se8)——java虚拟机结构(六)
2.11 指令集简介 java虚拟机指令由一个字节的操作码,接着时0个或多个操作数组成,操作码描述了执行的操作,操作数提供了操作所需的参数或者数据.许多指令没有操作数只包含一个操作码. 如果忽略异常处 ...
- java虚拟机规范(se8)——java虚拟机的编译(四)
3.12 抛出和处理异常 在程序中使用throw关键字来抛出异常.编译结果很简单. void cantBeZero(int i) throws TestExc { if (i == 0) { thro ...
- java虚拟机规范(se8)——java虚拟机的编译(一)
本文翻译自:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html 第三章 java虚拟机的编译 java虚拟机是设计用来支持ja ...
- java虚拟机规范(se8)——java虚拟机结构(三)
2.6. 栈帧 栈帧用于存储数据和部分结果,同样也用于执行动态链接,返回方法的值和分派异常. 当方法被调用的时候会创建一个新的栈帧.当一个方法调用结束时,它对应的栈帧就被销毁了,不管是正常调用结束还是 ...
- java虚拟机规范(se8)——java虚拟机结构(五)
2.10 异常 java虚拟机中的异常用Throwable类或者它的子类的实例来表示.抛出一个异常会导致立即非本地(an inmediate nolocal)的控制转移,从发生异常的地方跳到处理异常的 ...
- java虚拟机规范(se8)——java虚拟机结构(四)
2.7 对象的表示 java虚拟机并不要求对象满足任何特定的内部结构. 在Oracle的一些Java虚拟机实现中,对类实例的引用是指向句柄的指针,该句柄本身是一对指针:一个指向包含对象方法的表和指向表 ...
- java虚拟机规范(se8)——java虚拟机的编译(三)
3.6 接受参数 如果n个参数传给一个实例的方法,按照约定,它们被接受并放在这个新方法创建的栈帧中的局部变量表里,在局部变量表中的序号从1到n.这些参数按照它们传递过来的顺序存放.例如: int ad ...
- java虚拟机规范(se8)——java虚拟机的编译(二)
3.3 算术运算 java虚拟机通常在操作数栈上进行算术运算(例外情况是iinc指令,它直接增加一个局部变量的值).例如下面的align2grain()方法,它的作用是将int值对齐到2的指定次幂: ...
随机推荐
- JMeter学习笔记——认识JMeter(1)
拿到一个自动化测试工具,我们第一步就应该了解它能提供我们哪方面的功能(最直接的方法就是从官网获取),接下来就是简单的对这个工具进行“功能测试”了,当然这里的功能测试不是让你找它存在的bug,而是让自己 ...
- Linux用户管理机制
Linux系统中的用户管理涉及用户账号文件 /etc/passwd.用户密码文件 /etc/shadow.用户组文件 /etc/group. 一.用户账号文件 /etc/passwd 该文件为纯文本文 ...
- flex与滚动冲突
如果设置方向用了flex,那么用滚动就没用
- 4 vuex的安装
安装可以看,引入又问题https://blog.csdn.net/u014196765/article/details/78022065?locationNum=9&fps=1(引入) htt ...
- C语言变长数组data[0]
1.前言 在刷题时遇到一个结构中包含char data[0],第一次见到时感觉很奇怪,数组的长度怎么可以为零呢?于是上网搜索一下这样的用法的目的,发现在linux内核中,结构体中经常用到data[0] ...
- IntelliJ IDEA中文乱码问题
转自 https://blog.csdn.net/m0_37893932/article/details/78280663 1 file->settings->appearence里面有 ...
- Hbase之JAVA API不能远程访问问题解决
1.配置Linux的hostname2.配置Linux的hosts,映射ip的hostname的关系3.配置访问windows的hosts 参考文档:http://blog.csdn.net/ty49 ...
- docker--从仓库下载镜像到推送自己的项目到仓库步骤详解
怎样从仓库下载的镜像,变成容器,并在容器中制作项目,再将容器变成镜像,然后将镜像推送到仓库? 一:从官网下载镜像 官方的https://hub.docker.com/提供了数十万个镜像提供大家下载 以 ...
- Mouse Hunt CodeForces - 1027D(思维 找环)
Medicine faculty of Berland State University has just finished their admission campaign. As usual, a ...
- winform程序关闭界面时弹出提示框
void Form1_FormClosing(object sender, FormClosingEventArgs e){ if (MessageBox.Show( "窗口关闭后,数据即将 ...