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

Annotation processing causes NPE during flow analysis

XMLWordPrintable

    • b26

        When compiling a class that imports a class referenced from a Jar, that in turn extends a class to be generated during annotation processing, a NullPointerException can occur.

        Steps to reproduce:

        A.java:
        package t1;

        public @interface A {
        }

        B.java:
        package t2;

        public class B {
        }

        C.java:
        package t3;

        import t2.B;

        public class C extends B {
        }

        D.java:
        import t1.A;
        import t3.C;
        import t2.B;

        @A
        public class D {
        }

        P.java:
        import java.io.IOException;
        import java.io.Writer;
        import java.util.Set;

        import javax.annotation.processing.AbstractProcessor;
        import javax.annotation.processing.RoundEnvironment;
        import javax.annotation.processing.SupportedAnnotationTypes;
        import javax.lang.model.SourceVersion;
        import javax.lang.model.element.TypeElement;
        import javax.lang.model.util.ElementFilter;
        import javax.tools.Diagnostic;
        import javax.tools.JavaFileObject;

        @SupportedAnnotationTypes("t1.A")
        public class P extends AbstractProcessor {

            private static final String B_JAVA = "package t2; public class B {}";

            @Override
            public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
                for (TypeElement te : ElementFilter.typesIn(roundEnv.getRootElements())) {
                    createFile(te);
                }
                return true;
            }

            private void createFile(TypeElement te) {
                // Generate B.java when the processor reads the @A annotation on D
                if ("D".equals(te.getSimpleName().toString())) {
                    try {
                        JavaFileObject fo = processingEnv.getFiler().createSourceFile("B");
                        try (Writer out = fo.openWriter()) {
                            out.write(B_JAVA);
                        }
                    } catch (IOException e) {
                        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "problem writing file: " + e);
                    }
                }
            }

            @Override
            public SourceVersion getSupportedSourceVersion() {
                return SourceVersion.latestSupported();
            }
        }

        Compile processor:
        javac P.java t1/A.java t2/B.java t3/C.java

        Create Jar containing C:
        jar -cf t3.jar t3/C.class

        Delete B:
        rm t2/B.*

        Compile D with processor P and observe NullPointerException:
        javac -processor P D.java
        An exception has occurred in the compiler (16-internal). 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, the following diagnostic, and the parameters passed to the Java compiler in your report. Thank you.
        java.lang.NullPointerException: Cannot read field "kind" because "tree.sym" is null
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitIdent(Flow.java:2756)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCIdent.accept(JCTree.java:2407)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:440)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1664)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scanExpr(Flow.java:1921)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitApply(Flow.java:2623)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1745)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:440)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1664)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.visitExec(TreeScanner.java:219)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1532)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:440)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1664)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitBlock(Flow.java:2197)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1047)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:440)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1664)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitMethodDef(Flow.java:2100)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:893)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:440)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1664)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitClassDef(Flow.java:2038)
        at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:790)
        at jdk.compiler/com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:440)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1664)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.analyzeTree(Flow.java:2806)
        at jdk.compiler/com.sun.tools.javac.comp.Flow$AssignAnalyzer.analyzeTree(Flow.java:2788)
        at jdk.compiler/com.sun.tools.javac.comp.Flow.analyzeTree(Flow.java:217)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1404)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1378)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:973)
        at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:317)
        at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:176)
        at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:64)
        at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:50)
        printing javac parameters to: /tmp/javac.20201120_161206.args

              ebaron Elliott Baron
              ebaron Elliott Baron
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: