JDK-8062359 : javac Attr crashes with NPE in TypeAnnotationsValidator visitNewClass
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: os_x
  • CPU: x86
  • Submitted: 2014-10-28
  • Updated: 2015-10-30
  • Resolved: 2014-11-21
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 b42Fixed
Description
FULL PRODUCT VERSION :
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)


A DESCRIPTION OF THE PROBLEM :
I have not been able to isolate a simple test case, but when attempting to compile the 1.8 JDK source code with the 1.8 Java compiler, it crashes in Attr.TypeAnnotationsValidator.visitNewClass:

Caused by: java.lang.NullPointerException
	at com.sun.tools.javac.comp.Attr$TypeAnnotationsValidator.visitNewClass(Attr.java:4504)
	at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1516)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
	at com.sun.tools.javac.tree.TreeScanner.visitApply(TreeScanner.java:200)
	at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1465)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.tree.TreeScanner.visitReturn(TreeScanner.java:185)
	at com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1384)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
...

Inspecting the code in question (from Attr.java), it's clear that the code is in error:

        public void visitNewClass(JCNewClass tree) {
            if (tree.clazz.hasTag(ANNOTATED_TYPE)) {
                checkForDeclarationAnnotations(((JCAnnotatedType) tree.clazz).annotations,
                        tree.clazz.type.tsym);
            }
            if (tree.def != null) {
                checkForDeclarationAnnotations(tree.def.mods.annotations, tree.clazz.type.tsym);
            }
            if (tree.clazz.type != null) {
                validateAnnotatedType(tree.clazz, tree.clazz.type);
            }
            super.visitNewClass(tree);
        }

The "if (tree.def != null)" conditional goes on to call "tree.clazz.type.tsym" and the crash is because "tree.clazz.type" is null. The very next line of code checks whether "tree.clazz.type" is non-null, so clearly the expectation is that null is possible there. I assume the preceding code should also be guarded by a "three.clazz.type != null" check, but I don't know this code well enough to be sure that that is the correct solution.

I will say that with that null check inserted, the openjdk8u-dev branch of langtools is able to compile the JDK 1.8 source without crashing. It crashes in the same way as the shipped compiler without the check.

REGRESSION.  Last worked in version 8u5

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Unfortunately I can't trigger the bug in any simple way. It occurs inside a code analysis tool that I've written which uses JavacTool to analyze/attribute Java code.

However, this same bug appears to crop up in other circumstances as evidenced by a Google search for "TypeAnnotationsValidator NullPointerException". For example: https://netbeans.org/bugzilla/show_bug.cgi?id=242717

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No null pointer exception.
ACTUAL -
The null pointer exception described above.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Caused by: java.lang.NullPointerException
	at com.sun.tools.javac.comp.Attr$TypeAnnotationsValidator.visitNewClass(Attr.java:4504)
	at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1516)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
	at com.sun.tools.javac.tree.TreeScanner.visitApply(TreeScanner.java:200)
	at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1465)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.tree.TreeScanner.visitReturn(TreeScanner.java:185)
	at com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1384)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
	at com.sun.tools.javac.comp.Attr$TypeAnnotationsValidator.visitBlock(Attr.java:4537)
	at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:909)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.comp.Attr$TypeAnnotationsValidator.visitMethodDef(Attr.java:4475)
	at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:778)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.comp.Attr$TypeAnnotationsValidator.visitClassDef(Attr.java:4532)
	at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:693)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.tree.TreeScanner.visitNewClass(TreeScanner.java:208)
	at com.sun.tools.javac.comp.Attr$TypeAnnotationsValidator.visitNewClass(Attr.java:4509)
	at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1516)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.comp.Attr$TypeAnnotationsValidator.visitVarDef(Attr.java:4484)
	at com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:852)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.comp.Attr$TypeAnnotationsValidator.visitClassDef(Attr.java:4532)
	at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:693)
	at com.sun.tools.javac.comp.Attr.validateTypeAnnotations(Attr.java:4430)
	at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:4354)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4231)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4180)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4180)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4184)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4180)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4180)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4180)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4180)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4160)
	at com.sun.tools.javac.comp.Attr.visitClassDef(Attr.java:851)
	at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:693)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:566)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:635)
	at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:4321)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4231)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4160)
	at com.sun.tools.javac.comp.Attr.attrib(Attr.java:4135)
	at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1248)
	at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1221)
	at com.sun.tools.javac.api.JavacTaskImpl.analyze(JavacTaskImpl.java:364)
	at com.sun.tools.javac.api.JavacTaskImpl.analyze(JavacTaskImpl.java:344)
	at codex.extract.JavaExtractor.process0(JavaExtractor.java:106)
	... 14 more


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
The tree it is processing when it crashes is:

new PrivilegedAction<Boolean>(){
    public Boolean run() {
        try {
            type.getDeclaredMethod("processInputMethodEvent", InputMethodEvent.class);
            return Boolean.TRUE;
        } catch (NoSuchMethodException exception) {
            return Boolean.FALSE;
        }
    }
}

which is from line 3888 of javax/swing/text/JTextComponent.java (from the JDK).
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Insert the null check and compile my own version of langtools.


Comments
To reproduce (at least one possible code that relates to the JTextComponent problem cited here; this is unlikely to be the NetBeans problem): --- /** * @test * @compile/fail -XDdev JDK8062359.java */ public class JDK8062359 { public static void main(String[] args) { new Undefined() { void test() { new Object() {}; } }; } } ---
18-11-2014

Out for review: http://mail.openjdk.java.net/pipermail/compiler-dev/2014-November/009156.html
18-11-2014