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

Unexpected StackOverflowError when using 'limit' on infinite list generated with recursive 'flatMap' call

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "9"
      Java(TM) SE Runtime Environment (build 9+181)
      Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      The 'limit' method is specified to be a short-circuiting operation, but when used on an infinite Stream generated through use of 'flatMap' the limit is inconsistently applied, leading to a StackOverflowError.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run the attached code. The problem occurs with primitive streams (IntStream and company) or the generic object Stream.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The code should print
      4
      3
      2
      1
      0
      and then exit cleanly
      ACTUAL -
      The code prints
      4
      3
      2
      1
      0
      and then throws a StackOverflowError

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Exception in thread "main" java.lang.StackOverflowError
      at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
      at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
      at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:591)
      at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:272)
      at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
      at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
      at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
      at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
      at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
      at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:591)
      at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:272)
      at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
      at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
      at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
      at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
      at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
      at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:591)
      at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:272)

      (etc.)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.IntStream;

      public class StreamBugTest {
          public static void main(String[] args) {
              getChildren(5).limit(5).forEach(System.out::println);
          }

          private static IntStream getChildren(int i) {
              return IntStream.rangeClosed(i - 1, i + 1).flatMap(c -> IntStream.concat(IntStream.of(c), StreamBugTest .getChildren(c)));
          }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Must re-write code

            psandoz Paul Sandoz
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: