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

Arrays.copyOf -> race condition by coping arrays

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 8u25
    • hotspot
    • x86_64
    • windows_7

      FULL PRODUCT VERSION :
      1.8.0_25
      SE <build 1.8.0_25-b18>
      HotSpot 64-Bit Server VM <build 25.25-b02, mixed mode>

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      allocate primitive float[] with start size
      add single floats with increase index until length exceeded -> catch IndexOutOfBounds with exception and copy into new array[] with increased size
      proceed adding single floats.
      compare if all values are correct set.

      > on certain occasions after copy operation next value is not inserted correctly
      > test is run without concurrency (single thread)

      ADDITIONAL REGRESSION INFORMATION:
      not tested.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      can be reproduced just run @Test
      array size on Error occurance change

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      inserted correct value.

      expected - no race conditions - but it seems like creating one

      this.arr = Arrays.copyOf(this.arr, newSize);
      this.arr[this.items] = val;


      ACTUAL -
      occasional race condition occure.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      no crash (Exceptio) - just not conform - but seems to create a race condition

      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      public class DynArr_float {

         private int growthFactor;
         private int items;
         private float[] arr;

         public DynArr_float(int initCapacity, int growthFactor){
            this.init(initCapacity, growthFactor);
         }

         private void init(int initCapacity, int growthFactor){
            this.arr = (initCapacity>1) ? new float[initCapacity] : new float[1];
            this.growthFactor = (growthFactor > 1) ? growthFactor : 2;
            this.items = 0;
         }

         public float get(int i){
            if (i>=this.items) throw new IndexOutOfBoundsException();
            return this.arr[i];
         }


         public int add(float val){
            int t=0;
            try {
               this.arr[this.items]=val;
               t=this.items;
               this.items++;
            } catch (IndexOutOfBoundsException e){
               int newSize = Math.round(this.arr.length*this.growthFactor);
               this.arr = Arrays.copyOf(this.arr, newSize);
               this.arr[this.items] = val;
               t=this.items;
               this.items++;
            }
            return t;
         }
      }


      @Test
      public void DynArr_float() {
         Random rand = new Random();
         
          // different initial capacity and growth factor change race condition occurance
         DynArr_float f = new DynArr_float(0,0);
         
         boolean testresult=true;
         int in=0;
         int ifail=0;
         try {
            for (int i=0; i<1_000_000; i++){
            val = rand.nextFloat();
            in = f.add(val);

                // checks versus first occurance of failures
            if (val!=f.get(in) && testresult) {
               testresult = false;
               ifail=in;
            }
         }
            Debug.println("Index of fail", "after " + ifail);
         } catch (Exception e){
            fail(e.getMessage());
         }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      > open right now

            roland Roland Westrelin
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: