Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 5023712
Votes 8
Synopsis StrictMath.exp(1) doesn't always return the same double.
Category hotspot:runtime_system
Reported Against 1.4.2
Release Fixed
State 6-Fix Understood, bug
Priority: 4-Low
Related Bugs
Submit Date 30-MAR-2004
Description




FULL PRODUCT VERSION :
java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)

java version "1.4.2_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_01-b06)
Java HotSpot(TM) Client VM (build 1.4.2_01-b06, mixed mode)

java version "1.3.1_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_06-b01)
Java HotSpot(TM) Client VM (build 1.3.1_06-b01, mixed mode)

FULL OS VERSION :
Linux dhcp107136.sesp.northwestern.edu 2.4.19-gentoo-r10 #2 Thu Jun 26 11:29:51 CDT 2003 i686 Pentium  customer  (Coppermine) GenuineIntel GNU/Linux

(and various other Linux machines)
Not reproducible on Solaris or Windows.

A DESCRIPTION OF THE PROBLEM :
This is truly strange... I have one thread waiting on a lock  customer , and a second thread calls notifyAll() on the lock. The first thread wakes up, and from that point onward gets an incorrect value for StrictMath.exp(1). The value is missing one digit of precision, i.e. it is 2.718281828459045 rather than 2.7182818284590455. All other threads continue to get the correct value. This is not a string representation issue: the two double values are not ==.

This happens whether I use StrictMath or Math, whether or not the classes are strictfp, and whether or not java is started with -Xint.

This bug has serious implications for scientific applications of Java, since primitive mathematical functions may have non-deterministic behavior.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the attached code (jikes or javac), and run. If the problem is present, SOME of the numbers on lines beginning with "(MT)" will end ...45 rather than ...455 and the last line of the output will begin with "BAD NEWS". This happens 100% of the time on the several Linux machines I tested. Note that all values from the main thread remain correct.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The correct output (from a Windows machine) is:

$ java -jar tc.jar
(MAIN) HERE: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MAIN) BEFORE NOTIFY: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MAIN) AFTER NOTIFY: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MAIN) DOWN HERE: 2.7182818284590455
                                                                                
GOOD NEWS: values from both threads seem to match.
ACTUAL -
The output from my machine (with the bug):

[dhcp107136: bug]$ java -showversion -jar tc.jar
java version "1.4.2_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_01-b06)
Java HotSpot(TM) Client VM (build 1.4.2_01-b06, mixed mode)

(MAIN) HERE: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.7182818284590455
(MT) TOP OF LOOP: 2.7182818284590455
(MAIN) BEFORE NOTIFY: 2.7182818284590455
(MAIN) AFTER NOTIFY: 2.7182818284590455
(MT) BOTTOM OF LOOP: 2.718281828459045
(MT) TOP OF LOOP: 2.718281828459045
(MT) BOTTOM OF LOOP: 2.718281828459045
(MT) TOP OF LOOP: 2.718281828459045
(MT) BOTTOM OF LOOP: 2.718281828459045
(MT) TOP OF LOOP: 2.718281828459045
(MT) BOTTOM OF LOOP: 2.718281828459045
(MT) TOP OF LOOP: 2.718281828459045
(MAIN) DOWN HERE: 2.7182818284590455

BAD NEWS: two threads do NOT compute the same value for StrictMath.exp(1.0).


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public strictfp class TestCase
{
    private static double mostRecentInner;

    public static void main(String[] argv)
        throws Exception
    {
        System.out.println("(MAIN) HERE: " + StrictMath.exp(1.0));

        // start a new thread...
        MyThread th = new MyThread();
        th.start();

        // let it really start up...
        Thread.sleep(1000);

        // make it break!
        System.out.println("(MAIN) BEFORE NOTIFY: " + StrictMath.exp(1.0));
        synchronized (th._lock)
        {
            th._lock.notifyAll();
        }
        System.out.println("(MAIN) AFTER NOTIFY: " + StrictMath.exp(1.0));


        // let it go a few more times...
        Thread.sleep(1000);

        // done!
        System.out.println("(MAIN) DOWN HERE: " + StrictMath.exp(1.0));

        System.out.println();
        if (mostRecentInner != StrictMath.exp(1.0))
        {
            System.out.println("BAD NEWS: two threads do NOT compute the same "
                + "value for StrictMath.exp(1.0).");
        }
        else
        {
            System.out.println("GOOD NEWS: values from both threads seem to "
                + "match.");
        }
        System.exit(0);
    }

    private static strictfp class MyThread extends Thread
    {
        Object _lock = new Object();

        public void run()
        {
            try
            {
                while (true)
                {
                    System.out.println("(MT) TOP OF LOOP: "
                        + StrictMath.exp(1.0));
                    try
                    {
                        synchronized (_lock)
                        {
                            _lock.wait(300);
                        }
                    }
                    catch (InterruptedException e)
                    {
                        // ignore
                    }
                    mostRecentInner = StrictMath.exp(1.0);
                    System.out.println("(MT) BOTTOM OF LOOP: "
                        + StrictMath.exp(1.0));
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}
---------- END SOURCE ----------
(Incident Review ID: 209402) 
======================================================================
Work Around
Use a linux kernel > 2.4.19 or use -Xcomp.

  xxxxx@xxxxx   2004-08-05
Evaluation
Sounds like a bug; will investigate.

  xxxxx@xxxxx   2004-03-30

The bug doesn't occur using -Xcomp, but does using -Xint or no options.
The test is short enough that no options is the same as -Xint.

Kernel versions > 2.4.19 don't show the bug.  Kernel versions <= 2.4.19
have known thread problems.  This may be one of them.  It's possible the
OS is incorrectly restoring the value of a register or registers, or
messing with the page table.  Still investigating.

  xxxxx@xxxxx   2004-08-05
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang