JDK-8054210 : NullPointerException when compiling specific code.
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8u11
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2014-08-03
  • Updated: 2016-12-12
  • Resolved: 2014-09-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u40Fixed 9 b31Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_11"
Java(TM) SE Runtime Environment (build 1.8.0_11-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
It might be related to JDK-8042741, however my problem still exists in jdk8u20 EA but exception is different.

ADDITIONAL REGRESSION INFORMATION: 
The problem was first observed with EA builds of Java 8 (before official release of jdk8).

I did not have clue what part of code it was but now I know. 

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile attached code: 

javac TooMuchForACompiler.java

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Code compiles successfully (or produces reasonable error message). 
ACTUAL -
NullPointerException in a compiler

ERROR MESSAGES/STACK TRACES THAT OCCUR :


Error message for jdk8u11 (official release)


java.lang.NullPointerException
        at com.sun.tools.javac.comp.Flow$AbstractAssignAnalyzer.trackable(Flow.java:1476)
        at com.sun.tools.javac.comp.Flow$AbstractAssignAnalyzer.visitVarDef(Flow.java:1801)
        at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitVarDef(Flow.java:2516)
        at com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:846)
        at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:389)
        at com.sun.tools.javac.comp.Flow$AbstractAssignAnalyzer.scan(Flow.java:1367)
        at com.sun.tools.javac.comp.Flow$AbstractAssignAnalyzer.visitLambda(Flow.java:2225)


Error message for jdk8u20 EA: 

java.lang.NullPointerException
        at com.sun.tools.javac.code.Scope.includes(Scope.java:296)
        at com.sun.tools.javac.comp.Flow$1.trackable(Flow.java:247)
        at com.sun.tools.javac.comp.Flow$AbstractAssignAnalyzer.visitVarDef(Flow.java:1832)
        at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitVarDef(Flow.java:2569)



REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.function.Consumer;

public class TooMuchForACompiler {

    public interface Supplier<T, E extends Exception> {       
        T get() throws E;
    }

    public static <T, E extends Exception> T produceAndConsume(Supplier<T, E> supplier, Consumer<E> handler) {
        try {
            return supplier.get();
        } catch (Exception e) {
            handler.accept((E) e);

        }
        return null;
    }

    public static void main(String... args) {
        produceAndConsume(() -> -1, i -> System.out.println(i.getMessage()));
    }

}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Assign one of lambdas to a variable. 

 public static void main(String... args) {
        Supplier<Integer, RuntimeException> supplier = () -> -1;
        produceAndConsume(supplier, i -> System.out.println(i.getMessage()));
    }


Comments
Minimal test case: public class JDK8054210 { interface Thrower<E extends Exception> { void apply() throws E; } interface Consumer<E> { void take(E arg); } <E extends Exception> void m(Thrower<E> a1, Consumer<E> a2) {} void test() { m(() -> {}, e -> {}); } } Key element is a lambda parameter whose type is inferred from the thrown exceptions of another lambda. Edit: actually, this one fails, too: <E extends Exception> void m(Thrower<E> a1, Consumer<RuntimeException> a2) {} m(() -> {}, (RuntimeException e) -> {}); But it works if I change 'Thrower<E>' to 'Thrower<RuntimeException>'.
04-08-2014