跳到主要内容

JEP 306:恢复始终严格的浮点语义

概括

使浮点运算始终严格,而不是同时具有严格的浮点语义 ( strictfp) 和略有不同的默认浮点语义。这将恢复语言和 VM 的原始浮点语义,与 Java SE 1.2 中引入严格和默认浮点模式之前的语义相匹配。

目标

  • 简化数字敏感库的开发,包括java.lang.Mathjava.lang.StrictMath.

  • 在平台的棘手方面提供更多规律性。

非目标

定义任何类型的“fast-fp”或“loose-fp”并不是目标(参见JSR 84:浮点扩展)。

动机

1990 年代末改变平台默认浮点语义的动力源于原始 Java 语言和 JVM 语义之间的不良交互以及流行 x86 架构的 x87 浮点协处理器指令集的一些不幸的特性。在所有情况下匹配精确的浮点语义,包括次正规操作数和结果,需要大量额外指令的开销。在没有上溢或下溢的情况下匹配结果可以用更少的开销来实现,这大致是 Java SE 1.2 中引入的修订后的默认浮点语义所允许的。

然而,SSE2(流 SIMD 扩展 2)扩展在 Pentium 4 和大约 2001 年开始的更高版本处理器中提供,可以以简单的方式支持严格的 JVM 浮点运算,而无需过多的开销。

由于 Intel 和 AMD 都长期支持 SSE2 和更高版本的扩展,这些扩展允许对严格浮点语义的自然支持,因此具有不同于严格的默认浮点语义的技术动机不再存在。

描述

此 JEP 将修改的接口在其浮点表达式的覆盖范围中包括 Java 语言规范(请参阅JLS部分 4.2.3_浮点类型、格式和值_、5.1.13 *值集转换、15.4 FP 严格表达式、对第 15 章后面其他部分的许多小更新)以及 Java 虚拟机规范的类似部分(JVMS 2.3.2_浮点类型、值集和值_,第 2.8.2_浮点模式_,2.8.3_值集转换_,以及对各个浮点指令的许多小更新)。值集和值集转换的概念将从 JLS 和 JVMS 中删除。 JDK 中的实现更改包括更新 HotSpot 虚拟机,使其永远不会在浮点模式下运行,该模式允许扩展指数值集(此类模式必须存在于strictfp操作中),并更新javac以向不必要的使用发出新的 lint 警告的strictfp修改器。

测试

所有现有的数值测试在此更改后仍然有效,因为此更改始终使用当前允许的操作模式之一。

strictfp可以在没有修饰符的情况下复制现有的 Java 源测试。

风险和假设

提议的规范更改风险较低,主要是删除文本并更新 JLS 和 JVMS 中的浮点概述。该平台的原始语义被恢复,并且仅严格始终是允许的实现选项。因此,此 JEP 中的更改所带来的行为兼容性风险可以忽略不计。即使在可能发生非严格执行的平台上,也没有强制非严格评估的习惯用法。为了健壮,代码必须在严格执行的情况下始终能够工作,这将再次成为唯一的选择。