The implementation of iteration for a forEach tag over an integer range builds an array of all the Integer objects in the range, and then obtains an iterator via Arrays.asList(...).iterator(). The unnecessarily consumes a large amount of heap space when the value of "end" is large. The method in this comment about performance is basically correct from a *time* perspective, but completely ignores *space* considerations. The patch to iterate over an integer range without undue heap space follows. For JSTL 1.1.1 in src/org/apache/taglibs/standard/tag/common/core/ForEachSupport.java: // Begin added by AO Industries, Inc. import java.util.NoSuchElementException; // End added by AO Industries, Inc. private ForEachIterator beginEndForEachIterator() { // Begin removed by AO Industries, Inc. // /* // * To plug into existing support, we need to keep 'begin', 'end', // * and 'step' as they are. So we'll simply create an Integer[] // * from 0 to 'end', inclusive, and let the existing implementation // * handle the subsetting and stepping operations. (Other than // * localizing the cost of creating this Integer[] to the start // * of the operation instead of spreading it out over the lifetime // * of the iteration, this implementation isn't worse than one that // * created new Integers() as needed from next(). Such an adapter // * to ForEachIterator could easily be written but, like I said, // * wouldn't provide much benefit.) // */ // Integer[] ia = new Integer[end + 1]; // for (int i = 0; i <= end; i++) // ia[i] = new Integer(i); // return new SimpleForEachIterator(Arrays.asList(ia).iterator()); // End removed by AO Industries, Inc. // Begin added by AO Industries, Inc. // This implementation does not require heap space in proportion to the number of iterations. return new SimpleForEachIterator( new Iterator() { private final int end = ForEachSupport.this.end; private int next = 0; public boolean hasNext() { return next <= end; } public Object next() { if(next > end) throw new NoSuchElementException(); return Integer.valueOf(next++); } public void remove() { throw new UnsupportedOperationException(); } } ); // End added by AO Industries, Inc. }
One observation: Integer.valueOf was added in Java 1.5, so we'll need to stick with new Integer(next++) in the iterator. - Thanks!!!
I've been looking into this further. This enhancement has already been made in the 1.2 series of standard taglib. I hope you will still add it to any future release of the 1.1 series.
This has already been fixed in trunk and will be included in 1.2.0.RC2. Leaving open for 1.1 but a new release of that branch is unlikely.
Closing as 1.2.1 is released and no new release of 1.1 is likely.