简体   繁体   中英

Not being able to stop at exception when using consecutive stream.flatMap

When debugging my code in IntelliJ IDEA I can't stop at an exception in certain cases when consecutive flatMap methods are used on a stream. Instead of stopping at exception, it stops in API's ReferencePipeline#flatMap method at line 271, with frames stack not showing the exception at all. Here's the simplest example possible:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class AssertTest {
    public static void main(String[] args) {
        Arrays.asList(
            Arrays.asList(0, 0, 0),
            Arrays.asList(1, 1, 1),
            Arrays.asList(2, 2, 2)
        )
            .stream()
            .flatMap(a -> test1(a).stream())
            .flatMap(a -> test2(a).stream())
            .collect(Collectors.toSet());
    }
    private static List<List<Integer>> test1(List<Integer> ints) {
        return Arrays.asList(ints);
    }
    private static List<List<Integer>> test2(List<Integer> ints) {
        throw new RuntimeException();
    }
}

Here's what I see in my IDE when I run the code in debugger:

在此处输入图片说明

If I comment out the line that says .flatMap(a -> test1(a).stream()) , then it stops at the exception as intended. The same occurs with assertions (replace throw new RuntimeException() with assert false and run with -ea ).

This issue concerns only the debugger: after the program crashes on exception, the stack trace contains the right place where the exception originated.

Exception in thread "main" java.lang.RuntimeException
    at mypkg.AssertTest.test2(AssertTest.java:23)
    at mypkg.AssertTest.lambda$main$1(AssertTest.java:16)
    at mypkg.AssertTest$$Lambda$2/14008398.apply(Unknown Source)
    at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:267)
    at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
    at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270)
    at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at mypkg.AssertTest.main(AssertTest.java:17)

Is this a bug? If so, is it mentioned anywhere? If not, where should I report it: Jetbrains, Oracle? Or is this the correct behavior?

Here's the answer I got from a Jetbrains developer after reporting a bug:

http://youtrack.jetbrains.com/issue/IDEA-126981?replyTo=27-763411

I can reproduce it only if I set any exception breakpoint to stop only on uncaught exceptions, is this the case?

Your exception is caught and re-thrown inside java, it is a downside of streams :( You'll need to stop on caught exceptions as well to be able to stop in your code.

Enabling stopping at caught exceptions fixes this for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM