JDK-8181464 : Invalid lambda in annotation causes NPE in Lint.augment
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8,9
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2017-06-02
  • Updated: 2021-06-11
  • Resolved: 2017-06-13
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 10
10 b12Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
The following ill-formed input crashes javac when annotation processing is enabled.

=== T.java
@interface A {
  Class<?> value();
}

@A(value = x -> x)
class T {}
=== P.java
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.TypeElement;

@SupportedAnnotationTypes("*")
public class P extends AbstractProcessor {
  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    return false;
  }
}
===

$ javac P.java
$ javac -fullversion -processor P T.java
javac full version "9-ea+172"
An exception has occurred in the compiler (9-ea). Please file a bug against the Java compiler via the Java bug reporting page (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include your program and the following diagnostic in your report. Thank you.
java.lang.NullPointerException
        at jdk.compiler/com.sun.tools.javac.code.Lint.augment(Lint.java:75)
        at jdk.compiler/com.sun.tools.javac.comp.Attr.visitVarDef(Attr.java:1128)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:950)
        at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:653)
        at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStat(Attr.java:723)
        at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStats(Attr.java:742)
        at jdk.compiler/com.sun.tools.javac.comp.Attr.visitLambda(Attr.java:2477)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:1801)
        at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:653)
        at jdk.compiler/com.sun.tools.javac.comp.Attr.visitLambda(Attr.java:2543)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:1801)
        at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:653)
        at jdk.compiler/com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:693)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.getAnnotationClassValue(Annotate.java:603)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.attributeAnnotationValue(Annotate.java:574)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.attributeAnnotationNameValuePair(Annotate.java:509)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.attributeAnnotationValues(Annotate.java:474)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.attributeAnnotation(Annotate.java:408)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.annotateNow(Annotate.java:334)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.lambda$annotateLater$0(Annotate.java:260)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.flush(Annotate.java:184)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.unblockAnnotations(Annotate.java:137)
        at jdk.compiler/com.sun.tools.javac.comp.Annotate.enterDone(Annotate.java:150)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.enterDone(JavaCompiler.java:1726)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.enterTrees(JavaCompiler.java:1054)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:923)
        at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:302)
        at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:162)
        at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:55)
        at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:41)
Comments
The problem is that we end up attributing a lambda parameter (visitVarDef) when no 'lint' exists - as we are in the middle of annotation processing. This problem can be reproduced in different ways - with slightly different execution paths - for instance, the provided test case fails when attempting to recovery-attr the lambda body. Other examples fails earlier than that: @A(value = (String x) -> x) class T {} The explicit lambda here will require an earlier evaluation of the lambda parameters. While a simple solution would be to simply ban lambda expressions in annotations, I note that this problem of javac crashing because of a 'null' Lint happens very frequently - and in cases where, if attribution could run its course, a regular error message would be displayed. So perhaps it's time we address this by having a 'dummy' Lint object which doesn't do anything instead of 'null' - that would let execution flow even in exceptional cases like this one.
02-06-2017