The post on http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
describes a (on first sight) trivial bug when parsing strings into Java Double objects. Runtime (java app hang): class runhang { public static void main(String[] args) { System.out.println("Test:"); double d = Double.parseDouble("2.2250738585072012e-308"); System.out.println("Value: " + d); } } DevTime (javac hang): class compilehang { public static void main(String[] args) { double d = 2.2250738585072012e-308; System.out.println("Value: " + d); } } The problem is that the estimation of halfUlp is too small in the case where the larger alternative is normal and the smaller is denormal. In this case, the first estimate for 2.22507385850720120e-308 is 2.225073858507200889...e-308, an error of -3.109754e-324 and the second is 2.225073858507201383...e-308, an error of 1.830902e-324 so the second should be chosen. Unfortunately, in the second case the calculated halfUlp is 2^-1076, which is wrong because the next lower number will be denormal. Because denormals don't have the implied 1 bit, they are less accurate than normals, so the next lower number will have the same precision as this number, not twice the precision. Therefore, the estimated halfUlp is too large: it must be 2^-1075. So, I think this may be the correct fix: --- /local/openjdk/jdk6/jdk/src/share/classes/sun/misc/FloatingDecimal.java 2011-02-01 15:28:10.550913741 +0000 +++ /local/icedtea6/openjdk/jdk/src/share/classes/sun/misc/FloatingDecimal.java2011-02-02 12:07:22.292913754 +0000 @@ -1549,7 +1548,7 @@ if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){ overvalue = true; // our candidate is too big. diff = bigB.sub( bigD ); - if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){ + if ( (bigIntNBits == 1) && (bigIntExp-1 > -expBias) ){ // candidate is a normalized exact power of 2 and // is too big. We will be subtracting. // For our purposes, ulp is the ulp of the Andrew.