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的指定次幂: ...
随机推荐
- 远程显示(操作) 服务器 GUI 程序(图形化界面) (基于 X11 Forwarding + Centos + MobaXterm)
在做 数据分析(数据挖掘 或 机器学习)的时候,我们经常需要绘制一些统计相关的图表,这些统计.绘图的程序常常是跑在服务器上的,可是服务器出于性能和效率的考虑,通常都是没有安装图形化界面的,于是这些统计 ...
- SP2713 GSS4
题目链接 这是一道假题,表面上看起来,好像使用了什么奇妙的操作,其实就是一个无脑暴力 我们会发现,即使是\(1e18\),在开方\(6\)次之后也已经变成了\(1\),而\(1\)再怎么开方还是\(1 ...
- 洛谷 P2542 [AHOI2005]航线规划 解题报告
P2542 [AHOI2005]航线规划 题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel星系 ...
- Philosopher
Description 给你一个长度为\(n\)的序列\(a_i\)和\(m\)次操作,要支持两种操作: \(1\ l\ r\ flag\):将\([l,r]\)内的数排序,\(flag=1\)表 ...
- 洛谷P4135 作诗
题意:[l,r]之间有多少个数出现了正偶数次.强制在线. 解:第一眼想到莫队,然后发现强制在线...分块吧. 有个很朴素的想法就是蒲公英那题的套路,做每块前缀和的桶. 然后发现这题空间128M,数组大 ...
- C++并发编程实战---阅读笔记
1. 当把函数对象传入到线程构造函数中时,需要避免“最令人头痛的语法解析”.如果传递了一个临时变量,而不是一个命名的变量:C++编译器会将其解析为函数声明,而不是类型对象的定义. 例如: class ...
- RabbitMQ集群和高可用配置
概述 RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python.Ruby..NET.Java.JMS.C.PHP.ActionScript.XMPP. ...
- php 访问错误日志
/usr/local/php/var/log/php-fpm.log」—————————
- Java基础-零拷贝技术应用案例
Java基础-零拷贝技术应用案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 零拷贝技术在Hadoop生态圈中很多组件得到应用,典型的比如kafka组件,它就很成功的应用了零拷贝 ...
- Spark记录-官网学习配置篇(一)
参考http://spark.apache.org/docs/latest/configuration.html Spark提供三个位置来配置系统: Spark属性控制大多数应用程序参数,可以使用Sp ...