JDK-4848022 : Request for dynamic shrinking of built-in array types
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.util
  • Affected Version: 1.4.1
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2003-04-14
  • Updated: 2006-11-18
  • Resolved: 2006-11-18
Related Reports
Relates :  
Relates :  
Description
Name: nt126004			Date: 04/14/2003


A DESCRIPTION OF THE REQUEST :
This RFE is for an extension to the array mechanism, which allows an array to be dynamically resized to a smaller size.  For example.
Object[] foo = new Object[10];
foo.setLength(5);

When setLength() is called, the array length is changed in place with no copying at all.  This can simply be done by reducing the size of the memory allocated for the array.  Any data beyond the new length is lost, and the memory becomes reclaimable by the GC.  Reducing an array in size is an irreversable operation -- there is no way to grow it back to the original size.  If setLength() is called with an argument greater than the current length of the array, an exception is thrown (IllegalArrayResizeException ?)

This bug is similar to bug #4090307, which one key difference:  The feature I am requesting ONLY allows arrays to be reduced in size, not grown.  Therefore, the objection with which the other bug was closed does not apply.

JUSTIFICATION :
A common problem is to fill elements of a large array where you don't know in advance how many elements there will be.  There are many ways to do this, for example:
1) Pre-allocate an array of the maximum allowed size
2) use a pattern in which a small array is allocated initially and each time its size is exceeded, the array is copied to a larger array.  For example, how ArrayList works.
3) use ArrayList to build the array and call toArray()  (this is equivalent to #2)

the problem with all these methods is that in the end, you may have an array that is too big.  It then requires yet another copy into a final array of the right size, which can be both time and memory intensive if the array is large.

This RFE elegantly solves the problem by allowing the over-allocated array to be  reduced to the proper size in a quick, constant time operation.

This may also help with bug 4724129, which is one of the top voted bugs in the JDC!

EXPECTED VERSUS ACTUAL BEHAVIOR :
New method call in the implicit array classes class:

void setLength(int newSize) throws IllegalArrayResizeException

New exception:

class IllegalArrayResizeException throws RuntimeException
N/A.  feature does not currently exist.

---------- BEGIN SOURCE ----------
// create and return new array filled with the elements returned by iterator
Object[] fillArray(java.util.Iterator it);
  Object[] a = new Object[10];
  int i=0;
  while (it.hasNext()) {
    if (i == a.length) {
       Object[] newa = new Object[a.size * 3];
       System.arraycopy(a, 0, newa, 0, a.size);
       a = newa;
    }
    a[i++] = it.next();
  }

  // if the RFE existed, could call
  // a.setLength(i);
  // return a;
  // and be done with it.

  // but instead have to allocate and copy one more time:
  Object[] finala = new Object[i];
  System.arraycopy(a, 0, finala, 0, i);
  return finala;
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
See description
(Review ID: 184009) 
======================================================================

Comments
EVALUATION Making immutable things mutable often looks like a performance win, but it may be a performance loss because it inhibits certain optimizations. And making arrays resizable would be a serious incompatible change. We clearly cannot do this. JDK 6 introduced Arrays.copyOf, which allows you to "resize" arrays in a convenient way. Of course, semantically it makes a copy, but a very good JVM can do the escape analysis to optimize away the need to do an actual copy, especially if the array is being shrunk. JVMs should compete on their ability to perform such difficult optimizations. The submitter is afraid of the cost of the final memory copy. But copying memory linearly is an operation that JVMs are very good at optimizing, and they are likely to get better yet. We believe that the memory copy will be a bottleneck in very few real-world applications.
18-11-2006

EVALUATION At this point, I don't believe there is a big win with built-in array resizing. Only being able to shrink an array, with the attendant new exception, is even less worthwhile. It will cause more ArrayIndexOutOfBoundsExceptions because a programmer now has to know the array declaration AND the resize sites. The evaluation of 4090307 is still true: "A resize() method that returned a new array would be possible. Note that the new standard collection classes in 1.2 that auto-extend are likely to be a better choice for many existing uses of arrays." Consequently, I am reassigning this to java.util for consideration in the Arrays class.
17-11-2006