JDK-8130677 : Arrays.copyOf -> race condition by coping arrays
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 8u25
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2015-07-02
  • Updated: 2015-07-07
  • Resolved: 2015-07-07
Related Reports
Duplicate :  
Description
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


Comments
I verified the fix for JDK-8066900 makes the bug go away
07-07-2015