跳到主要内容

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

QWen Max 中英对照 JEP 306: Restore Always-Strict Floating-Point Semantics

总结

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

目标

  • 简化对数值敏感的库的开发,包括 java.lang.Mathjava.lang.StrictMath
  • 在平台的一个棘手方面提供更多的规律性。

非目标

我们的目标并不是定义任何类型的“快速浮点”或“宽松浮点”(参见 JSR 84: Floating Point Extensions)。

动机

20 世纪 90 年代末,推动改变平台默认浮点语义的契机源于最初的 Java 语言和 JVM 语义与流行的 x86 架构的 x87 浮点协处理器指令集的一些特性之间存在不良交互。在所有情况下(包括非规格化操作数和结果)匹配精确的浮点语义需要大量额外指令的开销。而在没有溢出或下溢的情况下匹配结果可以以更少的开销实现,这大致就是 Java SE 1.2 中引入的修订后的默认浮点语义所允许的内容。

但是,SSE2(Streaming SIMD Extensions 2)扩展可以轻松支持严格的 JVM 浮点运算,而不会造成过多开销。SSE2 扩展包含在 2001 年左右推出的奔腾 4 及之后的处理器中。

由于 Intel 和 AMD 都长期支持 SSE2 及其后续扩展,这些扩展允许自然支持严格的浮点语义,因此默认浮点语义不同于严格语义的技术动机已不复存在。

描述

此 JEP 将修改的接口包括《Java 语言规范》中关于浮点表达式的部分(参见 JLS 的 4.2.3 节 浮点类型、格式和值、5.1.13 节 值集转换、15.4 节 FP-strict 表达式,以及第 15 章后面的许多小更新)和《Java 虚拟机规范》(JVMS) 中的类似部分(2.3.2 节 浮点类型、值集和值、2.8.2 节 浮点模式、2.8.3 节 值集转换,以及对各个浮点指令的许多小更新)。值集和值集转换的概念将从 JLS 和 JVMS 中移除。JDK 的实现更改将包括更新 HotSpot 虚拟机,使其永远不会运行允许扩展指数值集的浮点模式(这种模式要求在 strictfp 操作中存在),并更新 javac 以对不必要使用 strictfp 修饰符的情况发出新的 lint 警告。

测试

由于此更改始终使用当前允许的操作模式之一,因此所有现有的数值测试都将保持有效。

现有的使用 strictfp 的 Java 源代码测试可以在不使用该修饰符的情况下进行复制。

风险与假设

所提议的规范变更风险较低,主要是删除文本以及更新 JLS 和 JVMS 中的浮点数概述。平台的原始语义得以恢复,并且严格模式(strict-only)始终是一种可允许的实现选项。因此,此 JEP 中的变更带来的行为兼容性风险可以忽略不计。即使在可能发生非严格执行的平台上,也没有强制进行非严格求值的习惯用法。为了确保代码的稳健性,始终需要能够在严格执行的情况下正常工作,而这将再次成为唯一的选择。