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的指定次幂: ...
 
随机推荐
- [转帖] k8s dashboard 的创建 升级 以及 admin token的创建和简单使用.
			
Kubernetes Dashboard中的身份认证详解 https://jimmysong.io/posts/kubernetes-dashboard-upgrade/ Thu Nov 2, 201 ...
 - letsencrypt续期 最简单的续期方法更新证书
			
Let's Encrypt申请的证书会有三个月的有效期,如何更方便的续期呢? 关于证书续期: 所谓letsencrypt续期,续期相当于重新申请一次证书,然后在服务器端将过期的证书替换掉即可.由于这个 ...
 - 【设计模式】—— 策略模式Strategy
			
前言:[模式总览]——————————by xingoo 模式意图 定义一系列的算法,把他们封装起来,使得算法独立于适用对象. 比如,一个系统有很多的排序算法,但是使用哪个排序算法是客户对象的自有.因 ...
 - linux下彻底卸载mysql 图解教程
			
linux下彻底卸载mysql 图解教程 1.查找以前是否装有mysql 命令:rpm -qa|grep -i mysql可以看到如下图的所示: 说明之前安装了:MySQL-client-5.5.25 ...
 - Spring Shell介绍
			
最近开发中在下遇到了spring-shell开发工具的项目,现在整理了相关文章,以供大家学习 本博客相关的文章均是在Spring Shell 1.2.0的基础上建立 Spring Shell介绍 ...
 - 【BZOJ3139】[HNOI2013]比赛(搜索)
			
[BZOJ3139][HNOI2013]比赛(搜索) 题面 BZOJ 洛谷 题解 双倍经验
 - 基于Maven构建Web项目
			
1.下载Maven,并配置好环境变量 2.打开命令行窗口,输入以下命令构建Maven Web项目 mvn archetype:generate -DgroupId=com.hello -Dartifa ...
 - debian8.4 系统莫名没有声音
			
[http://www.linuxdiyf.com/viewarticle.php?id=437020 Debian8, 桌面环境是xfce4, 安装完成后发现前面板音频输出插孔正常,后面板的没声音. ...
 - k8s如何管理Pod(rc、rs、deployment)
			
是豆荚,可以把容器想像成豆荚里的豆子,把一个或多个关系紧密的豆子包在一起就是豆荚(一个Pod).在k8s中我们不会直接操作容器,而是把容器包装成Pod再进行管理(关于Pod,大家可以参考第十期的分享“ ...
 - 一些常见修改命令(针对ubuntu 14.04 持续更新中...)
			
1.PS1 在哪: echo $PS1 vi /etc/bash.bashrc /W输出最后一个目录 /w输出完整目录 2.设置静态IP地址:vim /etc/network/i ...