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

(coll) java.util.SubList.subList() unnecessarily prevents gc of original SubList

    XMLWordPrintable

    Details

    • Type: Enhancement
    • Status: Closed
    • Priority: P4
    • Resolution: Not an Issue
    • Affects Version/s: 6
    • Fix Version/s: 7
    • Component/s: core-libs
    • Labels:

      Description

      A DESCRIPTION OF THE REQUEST :
      This feature requests borders on being a bug report.

      In JDK 1.6.0_06 (and probably later versions), the method java.util.SubList.subList, which is in AbstractList.java, reads:

      public List<E> subList(int fromIndex, int toIndex) {
         return new SubList<E>(this, fromIndex, toIndex);
      }

      Because of the "this" reference passed to the child SubList constructor, the child SubList prevents the parent SubList from garbage collection. This could be avoided if the call were:

        return new SubList<E>(this.l, this.offset + fromIndex, this.offset + toIndex);

      (i.e. the list wrapped by the SubList should first be unwrapped, and then the original list should be re-wrapped with adjusted fromIndex and toIndex, instead of wrapping another SubList around the existing wrapper).

      With this modification, the program below would run without OutOfMemoryError. Additionally, this would improve performance for access to SubList elements, as the call stack wouldn't have to go through so many layers of wrapping.


      JUSTIFICATION :
      I have an application where a List of candidate items gradually gets restricted to a smaller and smaller sublist. If subList() was implemented the way I propose above, I could just keep track of one List object and my performance and memory usage would always be fine. In the current implementation, however, I also have to pass integers a, b - the range of my remaining list - to all operations that work on the list.

      This defeats the purpose of subList(), which was provided specifically so that operations on List wouldn't have to accept optional range parameters.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      1. The provided sample program completes without OutOfMemoryError.
      2. Accessing elements of an AbstractList.subList().subList()...subList() should be just as fast as accessing elements of an AbstractList.subList(), especially when the list implements RandomAccess.
      ACTUAL -
      Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
      at java.util.RandomAccessSubList.subList(AbstractList.java:762)
      at Tester.main(Tester.java:8)

      ---------- BEGIN SOURCE ----------
      import java.util.List;
      import java.util.Collections;

      public class Tester {
          public static void main(String[] args) {
              List<String> list = Collections.emptyList();
              for (int i = 0; i < 1000000000; i++) {
                  list = list.subList(0, 0);
              }
          }
      }


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

      CUSTOMER SUBMITTED WORKAROUND :
      Write my own

      static <E> List<E> subList(List<E> list)

      method which doesn't exhibit this behaviour. This is clumsy and is the kind of work of which the java core libraries should free us.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              mduigou Mike Duigou
              Reporter:
              ndcosta Nelson Dcosta (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: