JDK-8211161 : java.lang.ArithmeticException: divide by zero from java.text.DecimalFormat.format()
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.text
  • Affected Version: 11
  • Priority: P4
  • Status: Closed
  • Resolution: Cannot Reproduce
  • Submitted: 2018-09-26
  • Updated: 2025-08-19
  • Resolved: 2025-08-18
Related Reports
Relates :  
Description
In java.text.DecimalFormat.format(), there is a validation to check whether a number is negative zero or not and for that divide by zero is used to check for negative infinity which caused the  ArithmeticException when SIGFPE is enabled in the system.
Detecting whether a double is negative is easy with the exception of the value -0.0.  This is a double which has a zero mantissa (and exponent), but a negative sign bit.  It is semantically distinct from a zero with a positive sign bit, and this distinction is important to certain kinds of computations.  However, it's a little tricky to detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). Hence, to detect a negative zero, java.text.DecimalFormat.format() used the approach divide-by-zero to compare against negative infinity. This approach works in the normal scenario as SIGFPE traps are disabled by default for all platforms. However, it can result in java.lang.ArithmeticException if the trap is enabled. Proper detection of -0.0 is needed to deal with the issues raised by bugs 4106658, 4106667, and 4147706.

Solution:
The issue can be resolved if divide-by-zero approach is replaced with bitwise comparison to check the sign bit of the number is 1. I expect a better performance with this approach as we replace divide operation with a bitwise comparison. However, the performance with both the approach is similar (may be due to the divide operation optimized to compare the denominator against 0). 
 
In java/text/DecimalFormat.format() method, replace (number == 0.0 && 1/number < 0) with (number == 0.0 && (Double.doubleToLongBits(number) == 0x8000000000000000L)).
 
Steps to recreate:
export JAVA_HOME=~/openjdk/builds/hs/jdk-10.0.2+13/
$JAVA_HOME/bin/javac DFTest.java
$JAVA_HOME/bin/javac -h . DFTest.java
c++ -shared -fPIC  -I$JAVA_HOME/include -I$JAVA_HOME/include/linux DFTest.cpp -o libDFTest.so
export LD_LIBRARY_PATH=~/openjdk/testpgm/jni
$JAVA_HOME/bin/java DFTest
 
Without Fix:
enasser@jcllnx01:~/testpgm/jni$ $JAVA_HOME/bin/java DFTest
double : 0.0
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at java.base/java.text.DecimalFormat.format(DecimalFormat.java:596)
    at java.base/java.text.DecimalFormat.format(DecimalFormat.java:563)
    at DFTest.main(DFTest.java:20)
 
With Fix:
enasser@jcllnx01:~/testpgm/jni$ ~/openjdk/jdk/build/linux-x86_64-normal-server-release/images/jdk/bin/java DFTest
double : 0.0
double : .0

Comments
Although this is an issue that isn't inherently a bug as [~darcy] explained, below, with the fix to JDK-8362448 being integrated, the division does not exist any longer, so the exception won't happen. Thus I close it as not reproducible.
18-08-2025

Will be addressed with JDK-8362448
21-07-2025

The situation as described is not a bug. Java library code is justified in expected 1.0/0.0 to not throw an exception; this is required by the language the JVM specs. The JDK library code should not be written to by tolerant of CPUs being deliberately misconfigured.
26-09-2018

webrev from Nasser: http://cr.openjdk.java.net/~aleonard/8211161/
26-09-2018