Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6895092

final local primitive variable spontaneously changes value to 0

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Cannot Reproduce
    • Icon: P3 P3
    • 7
    • 6u16
    • hotspot
    • x86
    • linux

      FULL PRODUCT VERSION :
      java version "1.6.0_16"
      Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
      Java HotSpot(TM) 64-Bit Server VM (build 14.2-b01, mixed mode)


      java version "1.7.0-ea"
      Java(TM) SE Runtime Environment (build 1.7.0-ea-b73)
      Java HotSpot(TM) 64-Bit Server VM (build 17.0-b02, mixed mode)

      FULL OS VERSION :
      1. Linux nibbler 2.6.28-15-generic #52-Ubuntu SMP Wed Sep 9 10:48:52 UTC 2009 x86_64 GNU/Linux
      2. Linux cunningham-linux 2.6.28-15-generic #49-Ubuntu SMP Tue Aug 18 19:25:34 UTC 2009 x86_64 GNU/Linux
      3. Linux invariant 2.6.28-15-generic #49-Ubuntu SMP Tue Aug 18 19:25:34 UTC 2009 x86_64 GNU/Linux


      EXTRA RELEVANT SYSTEM CONFIGURATION :
      1. dual Xeon W5580s
      2. dual Xeon X5550s
      3. dual Opteron 275s


      A DESCRIPTION OF THE PROBLEM :
      In the following method, I declare and init a local variable "final float x = a - b;". Variables "a" and "b" always have values 0.9672 (approx) and 0.0014 (approx). Variable "x" is always inited to 0.9658 (approx). Usually, "x" behaves as it should. Sometimes, however, "x" is found to have been spontaneously reset to 0.0 by the time we reach the end of the method.

      I have 16 threads executing this method simultaneously. The threads have no shared variables at all.


          public void update()
          {
              float a = (float) Math.exp(-1f / 30f); // always 0.9672
              float b = (1 - a) / 23f; // always 0.0014
              
              float[][] sheetSum = new float[ni][nj];
              
              final float x = a - b; // always 0.9658
              for (Sheet sheet : sheets) sheet.multiplyAndAdd(x, sheetSum);
              
              
              // XXX: x should still be 0.9658, but is sometimes 0.0 (yikes!)
              if (x < 0.01) log("Local variable changed spontaneously: a = " + a + ", b = " + b + ", x = a - b = " + x);
          }


      Looking at the values that wind up in the "sheets" array, it is apparent that "x" starts with value 0.9658, but changes to 0.0 partway through the loop.

      There's no way a final local primitive should ever change value. Ever. Yikes.


      Consistently reproducible on several machines running Ubuntu Jaunty, with Sun JVM 1.6.0_16, and 1.7-beta. Bug does not occur on these machines with JRockit-3.1.0-1.6.0.

        Bug does not occur with Sun JVM 1.6.0_16 on Windows.

      THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

      THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Run the code below on Ubuntu Jaunty, 64-bit, preferrably on a machine with dual Xeon 55xx CPUs
      2. Let it run for ~30 minutes, and watch for my log message

      I know it's annoying to wait 30 minutes to reproduce, but this is a serious bug.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Expected: final local primitive should keep the value it was initialized with.

      Actual: final local primitive is sometimes reset to 0.0.
      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      package com.metsci.curvejumps;

      import static com.metsci.curvejumps.Main.log;

      import java.text.DateFormat;
      import java.text.SimpleDateFormat;
      import java.util.Date;

      public class Main
      {
          private static final DateFormat timeFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          
          public static void log(String message)
          {
              String time;
              Date now = new Date();
              synchronized (timeFormatter) { time = timeFormatter.format(now); }
              
              System.err.println(time + " - " + Thread.currentThread().getName() + " - " + message);
          }
          
          public static void main(String[] args) throws Exception
          {
              log("Please let this run for about 30 minutes");
              log("");
              log("If the problem is detected, you will see a message saying \"local variable changed spontaneously\"");
              log("Otherwise, nothing further will be printed");
              log("");
              
              
              final int numThreads = 16;
              final int numUpdates = 129600;
              final int numSheets = 24;
              final int ni = 100;
              final int nj = 100;
              
              for (int t = 0; t < numThreads; t++)
              {
                  Thread thread = new Thread("Thread " + t)
                  {
                      public void run()
                      {
                          while (true)
                          {
                              SheetStack stack = new SheetStack(numSheets, ni, nj);
                              for (int n = 0; n < numUpdates; n++) stack.update();
                          }
                      }
                  };
                  thread.start();
              }
          }
      }


      class SheetStack
      {
          private final Sheet[] sheets;
          private final int ni;
          private final int nj;
          
          public SheetStack(int numSheets, int ni, int nj)
          {
              sheets = new Sheet[numSheets];
              for (int k = 0; k < sheets.length; k++) sheets[k] = new Sheet(ni, nj);
              
              this.ni = ni;
              this.nj = nj;
          }
          
          public void update()
          {
              float a = (float) Math.exp(-1f / 30f); // always 0.9672
              float b = (1 - a) / 23f; // always 0.0014
              
              float[][] sheetSum = new float[ni][nj];
              
              final float x = a - b; // always 0.9658
              for (Sheet sheet : sheets) sheet.multiplyAndAdd(x, sheetSum);
              
              // XXX: x should still be 0.9658, but is sometimes 0.0 (yikes!)
              if (x < 0.01) log("Local variable changed spontaneously: a = " + a + ", b = " + b + ", x = a - b = " + x);
          }
      }


      class Sheet
      {
          private final float[][] values;
          
          public Sheet(int side1CellCount, int side2CellCount)
          {
              values = new float[side1CellCount][side2CellCount];
          }
          
          public void multiplyAndAdd(float factor, float[][] addend)
          {
              for (int i = 0; i < values.length; i++)
              {
                  float[] valuesRow = values[i];
                  float[] addendRow = addend[i];
                  for (int j = 0; j < valuesRow.length; j++)
                  {
                      valuesRow[j] = (factor * valuesRow[j]) + addendRow[j];
                  }
              }
          }
          
          public void addTo(float[][] accumulator)
          {
              for (int i = accumulator.length; --i >= 0; )
              {
                  float[] valuesRow = values[i];
                  float[] accumulatorRow = accumulator[i];
                  for (int j = accumulatorRow.length; --j >= 0; )
                  {
                      accumulatorRow[j] += valuesRow[j];
                  }
              }
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      JRockit.

            Unassigned Unassigned
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: