00:00

strictfp Keyword in Java – Meaning and Why It Is Now Obsolete

strictfp ("strict floating-point") is a Java modifier that once forced floating-point calculations in a class, interface or method to follow the IEEE 754 standard exactly, so results were identical on every platform. Since Java 17 (JEP 306) all floating-point arithmetic is strict by default, so the keyword no longer has any effect, and the compiler warns that it is redundant.

This tutorial explains what strictfp was for, where it can be written, why it became obsolete, and what to use when you need reproducible or exact numeric results today.

1. What strictfp Meant

Java has always promised "write once, run anywhere", including for arithmetic. Early x86 processors, however, computed float and double values in 80-bit registers with extra precision and range. To run fast on such hardware, Java 1.2 introduced two modes:

ModeBehaviour (Java 1.2 – 16)
Default floating-pointIntermediate results could use extended exponent range, so results could differ slightly between platforms
strictfpEvery intermediate result rounded to exact IEEE 754 single or double precision, giving bit-for-bit identical results everywhere

The differences were tiny and appeared mostly with very large or very small numbers (overflow and underflow in intermediate steps), but they mattered for scientific code that needed reproducible results.

2. Where strictfp Can Be Used

  • Classes (including nested classes): applies to all methods and initialisers in the class.
  • Interfaces: applies to all default and static methods and nested types.
  • Methods: applies to that method only (the method must have a body).

It cannot be used on variables, constructors or abstract methods.

StrictfpDemo.java
public class StrictfpDemo {
    // strictfp on a class applies to all its methods (legal, but redundant since Java 17)
    static strictfp class Calculator {
        double compound(double principal, double rate, int years) {
            double amount = principal;
            for (int i = 0; i < years; i++) amount *= (1 + rate / 100);
            return amount;
        }
    }

    // strictfp on a single method
    static strictfp double average(double... values) {
        double sum = 0;
        for (double v : values) sum += v;
        return sum / values.length;
    }

    public static void main(String[] args) {
        System.out.println("compound: " + new Calculator().compound(10_000, 7.5, 3));
        System.out.println("average:  " + average(0.1, 0.2, 0.3));
        System.out.println("Since Java 17 these results are identical with or without strictfp.");
    }
}
Output
compound: 12422.96875
average:  0.20000000000000004
Since Java 17 these results are identical with or without strictfp.

The code still compiles on modern Java, but javac -Xlint:strictfp (or simply -Xlint) prints: "as of release 17, all floating-point expressions are evaluated strictly and 'strictfp' is not required".

3. Why It Is Obsolete Since Java 17

Modern CPUs use SSE2 and later instruction sets, which perform exact IEEE 754 single and double arithmetic quickly. The performance reason for the non-strict mode disappeared, so JEP 306 ("Restore Always-Strict Floating-Point Semantics") made strict behaviour the only behaviour in Java 17:

  • All floating-point expressions are evaluated strictly, with or without the keyword.
  • strictfp remains a reserved keyword and is still accepted, so old code compiles.
  • Adding or removing it changes nothing; you can safely delete it from code that targets Java 17+.

4. strictfp vs StrictMath

strictfp controlled basic arithmetic (+ - * /). Library functions such as sin, log and pow are a separate matter:

MathVsStrictMath.java
public class MathVsStrictMath {
    public static void main(String[] args) {
        double x = 1.2345;
        // StrictMath always gives bit-for-bit identical results on every platform.
        // Math may use faster CPU-specific implementations (results stay within documented accuracy).
        System.out.println("StrictMath.sin(x) = " + StrictMath.sin(x));
        System.out.println("Math.sin(x)       = " + Math.sin(x));
        System.out.println("0.1 + 0.2         = " + (0.1 + 0.2) + "  (IEEE 754 rounding, on every JVM)");
    }
}
Output
StrictMath.sin(x) = 0.9439833239445111
Math.sin(x)       = 0.9439833239445111
0.1 + 0.2         = 0.30000000000000004  (IEEE 754 rounding, on every JVM)
  • StrictMath uses fixed algorithms (fdlibm) and returns bit-for-bit identical results on every platform.
  • Math may use faster, platform-specific intrinsics. Results stay within a documented error bound but may differ in the last bit between JVMs.
  • Use StrictMath when exact reproducibility of transcendental functions matters, for example in simulations compared across machines.

5. Strict Does Not Mean Exact

Strict IEEE 754 arithmetic is reproducible, not precise in decimal terms. 0.1 + 0.2 is 0.30000000000000004 on every JVM, with or without strictfp. For money and other exact decimal values, use BigDecimal, or store amounts in the smallest unit (such as cents) as long.

6. Summary

  • strictfp forced exact IEEE 754 floating-point semantics in a class, interface or method.
  • It existed so results would be identical across platforms when default arithmetic was allowed extra range.
  • Since Java 17 all floating-point arithmetic is strict, so the keyword has no effect and triggers a lint warning.
  • StrictMath gives reproducible library functions; BigDecimal gives exact decimal arithmetic.

Related Tutorials