2.3.2 浮点数类型和值集合,值
浮点数类型有浮点数和双精度数,它们在概念上与IEEE754的值和操作的规范的标准的32位单
精度以及64位的双精度有关联。
     
IEEE754标准不仅包括了正负的有符号的数还有正负的零,正负的无穷大,一个特定的不是数值的值。
这个不是数值的数被用来表示特定的无效的操作例如除数是0。

 

java虚拟机的每个实现被要求支持浮点数的值的两个标准的集合,即浮点数集合和双精度数集合。
此外,java虚拟机的一个实现可能以它的选项,支持科学记数法的值的集合。

 

        2.3.3 返回地址的类型和值
返回地址的类型被用在了java虚拟机的jsr,ret,jsr_w这些指令中。返回地址的类型的值是java虚拟机
指令的操作码的指针。不像数值的原生的类型,返回地址的类型没有对应于java编程语言的类型,并且
不能被运行的程序修改。

 

        2.3.4 布尔类型
尽管java虚拟机定义了布尔类型,但它仅提供了很有限的支持。没有仅显示在布尔值上的操作
的虚拟机指令。在java编程语言的表达式操作布尔值的,被编译成使用虚拟机的整数的数据类型的值。

 

java虚拟机直接支持布尔的数组。它的Newarray指令能够创建布尔值的数组。布尔类型的数组
能够使用字节的数组的指令baload和 bastore来读取和修改。

 

在甲骨文公司的java虚拟机实现中,在Java程序的布尔数组被编码成java虚拟机中的字节数组,
每个布尔元素使用8位。

 

java虚拟机编码布尔数组,使用1表示真,使用0表示假。java编程语言的布尔值被编译器映射为
java虚拟机的整数类型的值。

 

   2.4 引用类型和值
引用类型有三种,类的类型,数组的类型,接口的类型。它们的值被动态创建的类的实例,
数组,实现了接口的类的实例和数组等相应的引用。

 

一个数组的类型包括了一个单一维度的组件的类型。一个数组类型的组件的类型本身可能
就是一个数组类型。如果,从任何一个数组类型开始,考虑它的组件的类型,然后(如果
它的组件类型是一个数组类型)它的类型的组件的类型,等等,最终必须到达了一个组件
类型不是一个数组类型,这叫做数组类型的元素的类型。一个数组类型的元素的类型必须是
一个原生的类型,或者是一个类的类型或者是一个接口的类型。

 

一个引用的值可能是一个特定的空的引用,一个非对象的引用,表示为null.空的引用被初始化
为一个非运行时的类型,但可能被映射为任何类型。一个引用的类型的默认值是空引用。

 

这个规范没有具体地明确指明如何编码Null。

 

   2.5 运行时的数据区
java虚拟机定义了一个可变的运行时数据区域,在一个程序的执行期间使用这个数据区域。
这些数据区域的一部分在java虚拟机启动时被创建。并且仅在当java虚拟机退出时才销毁。
其它的数据区域是每个线程的。每个线程的数据区域是当一个线程创建时而创建,当线程
退出时,线程的数据区域被销毁。
   2.5.1  程序计数的寄存器
 java虚拟机能一起支持许多的线程。每个 java虚拟机的线程有它自己的程序计数的寄存器。
在任何一个点时,每个 java虚拟机的线程正在执行的是一个单独的方法的代码,命名为那个
线程的当前的方法。如果那个方法不是原生的,寄存器包括了正在执行的指令的地址。
如果被线程执行的方法是原生的,寄存器的值是未定义的。 java虚拟机的线程足够宽度
以保存返回地址或者是特定平台上的一个原生的指针。

 

   2.5.2  java虚拟机的栈
每个Java虚拟机的线程有一个私有的java虚拟机的栈,与线程创建时一起被创建的。
一个java虚拟机的栈存储帧。java虚拟机的栈与传统的C语言的栈类似。它存储局部变量和
中间结果,在方法调用与返回时保存结果。因为java虚拟机的栈只能被压帧入栈和弹帧出栈,
不能被直接操作,帧可能被堆分配。java虚拟机的栈的内存不需要是连续的。

 

在虚拟机规范的第一版本中,java虚拟机的栈被叫做java的栈。

 

规范允许java虚拟机的栈有固定的大小或者是动态地扩展大小,如果java虚拟机的栈
是固定的大小,每个java虚拟机的栈可能依赖于栈的创建。

 

一个java虚拟机实现可能提供了让编程员和用户控制java虚拟机的栈的初始时的大小,
正如可以动态地扩展或者是收缩栈的大小。

 

如下的异常条件与java虚拟机的栈是相关的:
在线程中的计算要求的栈太大,java虚拟机抛出栈溢出异常。
如果栈可以动态的扩展,扩展的执行却没有足够的内存可用,或者是没有足够的
内存用于为新的线程创建栈了,java虚拟机抛出内存不足的异常。

 

   2.5.3  堆
java虚拟机有一个堆在所有的java虚拟机的栈中进行共享。堆是运行时的数据区
它是为了所有的类的实例和数组分配的内存。

 

java虚拟机在启动时,创建了堆。堆存储的对象由一个自动的存储管理系统来决定。
(也就是垃圾回收系统)对象不能被显式的销毁。java虚拟机假定自动的存储管理
系统没有特定的类型,并且存储管理技术可能与实现者的系统需求密切相关。堆可
能有一个固定的大小或者是被计算需要而扩展,或者有一个大的堆变得不再需要了而收缩。
堆的内存不需要是连续的。

 

java虚拟机的实现可能提供了编程员对堆大小的控制。

 

如下的异常是与堆有关的:
   如果有计算需要的堆超过了自动存储管理系统能分配的大小,java虚拟机抛出内存不足的异常。

 

   2.5.4  方法区
java虚拟机有一个方法区供所有的java虚拟机的线程共享。方法区与传统语言的被编译的代码的存储区相似,
也与一个操作系统中的进程的文本的段类似。它存储着类的结构,例如运行时的常数池,域和方法数据,方法
的代码和组装子,包括了在类和接口和实例的初始化中使用的特定的方法。

 

java虚拟机在启动时,创建了方法区。尽管方法区是堆的逻辑的部分,简单的实现可能没有用垃圾回收的方法实现。这个规范没有指定方法区的位置和管理编译的代码的策略。方法区可
能有一个固定的大小或者是被计算需要而扩展,或者有一个大的方法区变得不再需要了而收缩。
方法区的内存不需要是连续的。

 

java虚拟机的实现可能提供了编程员对方法区大小的控制。

 

如下的异常是与方法区有关的:
   如果有计算需要的方法区超过了自动存储管理系统能分配的大小,java虚拟机抛出内存不足的异常。

 

   2.5.5   运行时的常数池
一个运行时常数池是在一个类文件中的常数池的表的一个类或者是一个接口的运行时的表示
它包括了几种常数,范围从在编译时的常数字面量到运行时的必须被解析的方法和域的引用。
运行时的常数池提供一个类似于传统的编程语言的符号表的作用,尽管它包括了比符号表更大的
范围的数据。

 

每个运行时的常数池,从方法区分配空间。被虚拟机在类或者是接口创建时组装好这个常数池。

 

它也有内存不足的异常可以发生。

 

   2.5.6  原生方法的栈
java虚拟机的实现可能使用传统的栈,叫做C栈,来支持原生的方法(方法以其它的语言写成)
原生的方法的栈也可能被使用来作java虚拟机的指令集的解释器的实现,例如以C语言写的。
java虚拟机的实现不能加载原生的方法,它本身依赖的传统的栈不提供原生的方法的栈。
如果提供,原生的方法的栈在每个线程创建时被每个线程分配空间。

 

这个规范允许 原生的方法栈有固定的大小或者是根据计算的需要扩展或者是收缩。如果它是固定的大小,
它的大小可能依赖于它被创建的时候。

 

   2.6 帧
一个帧被用来存储数据和部分结果,正如执行动态链接,返回方法的值和分发的异常。

 

每当一个方法被调用时,一个新的帧就创建了。当方法调用完成,帧就销毁了,无论它
是正常的完成还是有异常抛出。帧由创建帧的线程的java虚拟机的栈进行分配。每个帧
有它自己的局部变量的数组,它自己的操作数的栈,还有当前的方法的类的运行时的
常数池的一个引用。

 

一个帧可能被附加的与实现相关的信息进行扩展,例如调试信息。

 

局部变量的数组的大小和操作数的栈在编译时被确定,被关联到帧的方法的代码支持。
因此,帧数据结构的大小仅依赖于java虚拟机的实现,在方法创建时,这些结构的内存
能被同时分配。

 

仅有一个帧,就是正在执行的方法的帧是活跃的,在一个给定的受控制的线程中,在任何一点上。
这个帧被引用作为当前的帧,它的方法是当前的方法。在当前的方法中定义的类是当前的类。
在局部变量中的操作和操作数的栈一般被引用到当前的帧。

 

如果它的方法调用其它方法或者是它的方法完成了,这个帧就中止了。当一个方法被调用时,一个新的
帧被创建并且当控制转移到这个新的方法时成为当前帧。在方法返回,当前帧传递回它的方法的调用的
返回值给前一帧。当前帧被丢弃,前一帧成为当前的那一个。

注意一个帧被某个线程的内部线程创建,这个内部的线程不能被其它的线程引用。