java虚拟机规范(se8)——java虚拟机结构(四)
2.7 对象的表示
java虚拟机并不要求对象满足任何特定的内部结构。
在Oracle的一些Java虚拟机实现中,对类实例的引用是指向句柄的指针,该句柄本身是一对指针:一个指向包含对象方法的表和指向表示Class对象的指针对象的类型,另一个是从堆为对象数据分配的内存。
2.8 浮点算法
Java虚拟机包含IEEE二进制浮点运算标准(ANSI / IEEE Std.754-1985,New York)中规定的浮点运算的子集。
2.8.1 Java虚拟机浮点算法和IEEE 754
Java虚拟机支持的浮点运算与IEEE 754标准之间的主要区别是:
- IEEE 754中的定义的无效操作,如被0除,溢出,向下溢出或者不精确,在java虚拟机中不会抛出异常,或者其它IEEE 754中规定的表示方式。java虚拟机没有型号NaN值。(The Java Virtual Machine has no signaling NaN value. )
- JAVA虚拟机中不支持IEEE 754中的信号浮点比较。(The Java Virtual Machine does not support IEEE 754 signaling floating-point comparisons. )
- Java虚拟机的舍入操作始终使用IEEE 754舍入到最近模式。不精确的结果四舍五入到最接近的可表示值,并且保证此值的最低有效位为0,这是IEEE 754默认模式。但Java虚拟机指令将浮点类型的值转换为整数类型的值,向零舍入。Java虚拟机没有提供任何改变浮点舍入模式的方法。
- Java虚拟机不支持IEEE 754单扩展或双扩展格式,但是在双精度浮点数集合和双精度扩展指数集合范围与单精度扩展指数格式的表示会有重叠。单精度扩展指数和双精度扩展指数值集(可选择支持)与IEEE 754扩展格式的值不对应:IEEE 754扩展格式规定了扩展精度以及扩展指数范围。
2.8.2 浮点格式
每一个方法都有一个浮点模式,要么是FP-strict,要么时not FP-strict。方法的浮点格式由方法的method_info结构中access_flags项的ACC_STRICT标志来决定。如果设置了这个标志位就是FP-strict,否则就是not FP-strict。
请注意,ACC_STRICT标志的这种映射意味着由JDK 1.1版或更早版本中的编译器编译的类中的方法实际上时not FP-strict。
当调用创建包含操作数堆栈的帧的方法具有浮点模式时,我们将操作数堆栈称为具有给定的浮点模式。类似地,当包含该指令的方法具有该浮点模式时,我们将该Java虚拟机指令称为具有给定的浮点模式。
如果支持单精度扩展指数集(第2.3.2节),则非FP-strict的操作数堆栈上float类型的值可以超出该值集,除非值集转换禁止(§2.8.3))。如果支持双精度扩展指数集(第2.3.2节),则非FP-strict的操作数堆栈上的double类型值可以超出该值集,除非值集转换禁止。
在所有其他上下文中,无论是在操作数堆栈上还是在其他位置上,无论浮点模式如何,float和double类型的浮点值只能分别在单精度浮点集和双精度浮点集的范围内。特别是,类和实例字段、数组元素、局部变量和方法参数只能从标准值集中取值。
2.8.3 数值集转换
在一些特定场景下,支持扩展指数集合的 Java 虚拟机实现数值在标准浮点数集合与扩展指数集合之间的映射关系是允许和必要的,这种映射操作就称为数值集合转换数值集合转换并非数据类型转换,而是在同一种数据类型之中不同数值集合的映射操作。
在指示值集转换的情况下,允许实现对值执行以下操作之一:
- 如果一个值的类型为float,并且不是float值集的元素,则它将值映射到float值集的最近元素。
- 如果值的类型为double且不是double值集的元素,则它将值映射到double值集的最近元素。
另外,如果如果要进行数值集转换,则需要执行下面的操作:
- 假设非FP-strict的Java虚拟机指令执行时导致了float类型的值被推送到FP-strict的操作数堆栈,如作为参数传递,或存储到局部变量,字段或数组的元素。如果该值不是floa值集的元素,则将该值映射到float值集的最近元素。
- 假设非FP-strict的Java虚拟机指令执行时导致了double类型的值被推送到FP-strict的操作数堆栈,如作为参数传递,或存储到局部变量,字段或数组的元素。如果该值不是double值集的元素,则将该值映射到double值集的最近元素。
在方法调用期间传递浮点类型的参数(包括本地方法调用)可能会发生这种所需的值集转换,如:将浮点类型的值从非FP-strict的方法返回到FP-strict的方法、或者将浮点类型的值存储到非FP严格的方法中的局部变量,字段或数组中。
并非扩展指数值集中的所有值都可以精确映射到相应标准值集中的值。如果映射的值太大而无法准确表示(其指数大于标准值集允许的值),则将其转换为相应类型的(正或负)无穷大。如果映射的值太小而不能精确表示(其指数小于标准值集所允许的值),则将其舍入到最接近的可表示的非规范化值或相同符号的零。
数值集转换不会转换无限大、无限小和NaN并且不会改变值的符号。
2.9 特殊方法
从java虚拟机的维度来看,每一个使用java编程语言编写的构造器都是一个实例初始化方法(instance initialization method),并且有一个特殊的名字<init>。这个名称有编译器提供,因为<init>在java编程语言中不是一个合法的标识符,无法使用java编程语言编写。实例初始化方法只能被java虚拟机通过指令调用,并且只会被调用在未初始化的实例上。实例初始化方法和构造器的访问权限一致。
一个类或者接口最多只有一个类或接口初始化方法(class or interface initialization method),通过调用这个初始化方法来初始化这个类或者接口。类或者接口的初始化方法有一个特殊的名称<clinit>,它没有参数,并且返回值为void。
类文件中名为<clinit>的其他方法无关紧要。 它们不是类或接口初始化方法。 它们不能被任何Java虚拟机指令调用,并且永远不会被Java虚拟机本身调用。
在版本号为51.0或以上的类文件中,方法必须另外设置ACC_STATIC标志(§4.6),以便成为类或接口初始化方法。
这个需求是在Java SE 7中引入的。在版本号为50.0或更低的类文件中,一个名为<clinit>的方法返回值是void的,不接受任何参数,不管它的ACC_STATIC标志设置如何,都被认为是类或接口初始化方法。
<clinit>名称由编译器提供,因为这不是一个有效的标识符,它不能在java编程语言直接使用。类和接口的初始化方法被java虚拟机隐式调用,它们从来不会被java虚拟机指令直接调用,而是作为类初始化过程中一部分被间接调用。
如果下列条件都为真,则方法为签名多态(signature polymorphic):
- 它在java.lang.invoke.MethodHandle类中声明
- 它只有一个Object[] 参数
- 它的返回类型是Object
- 它的设置了
ACC_VARARGS和ACC_NATIVE标志位
在Java SE 8中,仅有的签名多态方法( signature polymorphic)是java.lang.invoke.MethodHandle类中的invoke 和 invokeExact方法。
Java虚拟机在invokevirtual指令中对签名多态方法进行了特殊处理,以实现方法句柄(method handle)的调用。方法句柄是对底层方法、构造函数、字段或类似低级操作(§5.4.3.5)的强类型,直接可执行的引用,具有可选的参数或返回值转换。这些转换非常普遍,包括转换、插入、删除和替换等模式。可以从Java SE平台API中的java.lang.invoke包中获取更多信息。
java虚拟机规范(se8)——java虚拟机结构(四)的更多相关文章
- java虚拟机规范(se8)——java虚拟机结构(一)
本文翻译自:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html 第二章 虚拟机结构 本文档描述了一个抽象的虚拟机规范,并不描述 ...
- java虚拟机规范(se8)——java虚拟机的编译(四)
3.12 抛出和处理异常 在程序中使用throw关键字来抛出异常.编译结果很简单. void cantBeZero(int i) throws TestExc { if (i == 0) { thro ...
- java虚拟机规范(se8)——java虚拟机结构(二)
2.5 运行时数据区域 java虚拟机定义了多个用于程序执行期间的运行时数据区域.这些数据区域中一些随着java虚拟机的启动而创建,随着虚拟机的退出而销毁.其他的数据区域时和线程相关的.线程相关数据区 ...
- java虚拟机规范(se8)——java虚拟机结构(六)
2.11 指令集简介 java虚拟机指令由一个字节的操作码,接着时0个或多个操作数组成,操作码描述了执行的操作,操作数提供了操作所需的参数或者数据.许多指令没有操作数只包含一个操作码. 如果忽略异常处 ...
- 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虚拟机的编译(三)
3.6 接受参数 如果n个参数传给一个实例的方法,按照约定,它们被接受并放在这个新方法创建的栈帧中的局部变量表里,在局部变量表中的序号从1到n.这些参数按照它们传递过来的顺序存放.例如: int ad ...
- java虚拟机规范(se8)——java虚拟机的编译(二)
3.3 算术运算 java虚拟机通常在操作数栈上进行算术运算(例外情况是iinc指令,它直接增加一个局部变量的值).例如下面的align2grain()方法,它的作用是将int值对齐到2的指定次幂: ...
随机推荐
- DELPHI 字符串与日期格式互转
procedure TForm1.Button1Click(Sender: TObject); var D:TDateTime; s:string; begin D:=VarToDateTime('0 ...
- js保留两位小数方法总结
js保留两位小数方法总结 最近在做结算系统,经常需要用到金额保留两位小数,刚开始我一直用的是Angular中的过滤器number |2,但是,这无法满足我的需求.问题是,当用户离开文本框时,我需要将用 ...
- AOP 如果被代理对象的方法设置了参数 而代理对象的前置方法没有设置参数 则无法拦截到
AOP 如果被代理对象的方法设置了参数 而代理对象的前置方法没有设置参数 则无法拦截到
- ubuntu关闭和开启防火墙
1.关闭ubuntu的防火墙 ufw disable 2开启防火墙 ufw enable 3.卸载了iptables apt-get remove iptables 4.关闭ubuntu中的防火墙的其 ...
- Fantastic Graph 2018 沈阳赛区网络预赛 F题
题意: 二分图 有k条边,我们去选择其中的几条 每选中一条那么此条边的u 和 v的度数就+1,最后使得所有点的度数都在[l, r]这个区间内 , 这就相当于 边流入1,流出1,最后使流量平衡 解析: ...
- MT【100】经典计数之分配问题
注意:此讲适合联赛一试学生,以及参加清华北大等名校的自主招生的学生. 经典计数之分配问题:把n个球放进k个盒子.考虑分配方法有三类:1.无限制 2.每个盒子至多一个(f 单的)3.每个盒子至少一个(f ...
- 解决 No Entity Framework provider found for the ADO.NET provider
方法很简单,添加下面的dll即可 EntityFramework.SqlServer.dll 疯吻IT
- BZOJ4589 Hard Nim(快速沃尔什变换FWT)
这是我第一道独立做出来的FWT的题目,所以写篇随笔纪念一下. (这还要纪念,我太弱了) 题目链接: BZOJ 题目大意:两人玩nim游戏(多堆石子,每次可以从其中一堆取任意多个,不能操作就输).$T$ ...
- 生成器 yield
由于生成器的其中一种创建方式与列表推导式很相似,这里先说一下列表推导式. 列表推导式 列表推导式又叫列表生成式,官方叫做 list comprehension.顾名思义,这个是用来生成列表的. 用法: ...
- POJ 1847 Tram (最短路径)
POJ 1847 Tram (最短路径) Description Tram network in Zagreb consists of a number of intersections and ra ...