JDK-6670278 : ClassCastException com.sun.tools.javac.tree.JCTree$JCErroneous in APT
  • Type: Bug
  • Component: tools
  • Sub-Component: apt
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2008-03-03
  • Updated: 2011-02-16
  • Resolved: 2009-09-22
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_03"
Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
Java HotSpot(TM) Client VM (build 1.6.0_03-b05, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
When running apt.exe, receive a dump about

   java.lang.ClassCastException:
    com.sun.tools.javac.tree.JCTree$JCErroneous cannot be cast to
    com.sun.tools.javac.tree.JCTree$JCAnnotation

This seems to be caused by a malformed annotation (the comma in the following):

  @Foo(fees = {@Fee(name = "aaa"),})

When only run through javac, the compiler properly reports the comma as an error. Removing the comma allows the annotation processor to run properly.

APT should report the same error instead of the stack dump.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Using the code below, run ant (1.7.0) against the build.xml

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Message from APT about invalid syntax at the comma.
ACTUAL -
Buildfile: C:\eclipse3311\workspace\AnnotationBugTest\build.xml
build:
    [javac] Compiling 1 source file to C:\eclipse3311\workspace\AnnotationBugTest\processor-bin
     [exec] An exception has occurred in apt (1.6.0_03). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
     [exec] java.lang.ClassCastException: com.sun.tools.javac.tree.JCTree$JCErroneous cannot be cast to com.sun.tools.javac.tree.JCTree$JCAnnotation
     [exec] 	at com.sun.tools.javac.comp.Annotate.enterAttributeValue(Annotate.java:205)
     [exec] 	at com.sun.tools.javac.comp.Annotate.enterAttributeValue(Annotate.java:219)
     [exec] 	at com.sun.tools.javac.comp.Annotate.enterAnnotation(Annotate.java:167)
     [exec] 	at com.sun.tools.javac.comp.MemberEnter.enterAnnotations(MemberEnter.java:743)
     [exec] 	at com.sun.tools.javac.comp.MemberEnter.access$300(MemberEnter.java:42)
     [exec] 	at com.sun.tools.javac.comp.MemberEnter$5.enterAnnotation(MemberEnter.java:711)
     [exec] 	at com.sun.tools.javac.comp.Annotate.flush(Annotate.java:95)
     [exec] 	at com.sun.tools.javac.comp.Annotate.enterDone(Annotate.java:87)
     [exec] 	at com.sun.tools.javac.comp.Enter.complete(Enter.java:472)
     [exec] 	at com.sun.tools.javac.comp.Enter.main(Enter.java:429)
     [exec] 	at com.sun.tools.apt.main.JavaCompiler.compile(JavaCompiler.java:250)
     [exec] 	at com.sun.tools.apt.main.Main.compile(Main.java:1102)
     [exec] 	at com.sun.tools.apt.main.Main.compile(Main.java:964)
     [exec] 	at com.sun.tools.apt.Main.processing(Main.java:95)
     [exec] 	at com.sun.tools.apt.Main.process(Main.java:43)
     [exec] 	at com.sun.tools.apt.Main.main(Main.java:34)

BUILD FAILED
C:\eclipse3311\workspace\AnnotationBugTest\build.xml:22: exec returned: 4

  Total time: 1 second


ERROR MESSAGES/STACK TRACES THAT OCCUR :
(see "actual result")

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
[If you would like a zip of the following code, please send me an email]

src/a/b/c/Sample.java
-----------------------------
package a.b.c;

import annotation.Fee;
import annotation.Foo;

@Foo(fees = {@Fee(name = "aaa"),})  // THE COMMA SEEMS TO BE THE CULPRIT...
public class Sample {
    // nothing
}

==========================================

src/annotation/Fee.java
--------------------------------
package annotation;

public @interface Fee {
    String name();
}

==========================================

src/annotation/Foo.java
--------------------------------
package annotation;

public @interface Foo {
    Fee[] fees();
}

==========================================

src/annotation/FooAnnotationProcessor.java
------------------------------------------------------------
package annotation;

import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;

public class FooAnnotationProcessor implements AnnotationProcessor {
    public FooAnnotationProcessor(AnnotationProcessorEnvironment env) { /* dummy */ }
    public void process() { /* dummy */ }
}

==========================================

src/annotation/FooAnnotationProcessorFactory.java
----------------------------------------------------------------------
package annotation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;

import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.apt.AnnotationProcessorFactory;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;

public class FooAnnotationProcessorFactory implements AnnotationProcessorFactory {
    private static final ArrayList<String> ANNOTATIONS = new ArrayList<String>();

    static {
        ANNOTATIONS.add(Foo.class.getName());
        ANNOTATIONS.add(Fee.class.getName());
    }

    public AnnotationProcessor getProcessorFor(Set<AnnotationTypeDeclaration> atds, AnnotationProcessorEnvironment env) {
        return new FooAnnotationProcessor(env);
    }

    public Collection<String> supportedAnnotationTypes() {
        return ANNOTATIONS;
    }

    public Collection<String> supportedOptions() {
        return Collections.emptyList();
    }
}

==========================================
src/META-INF/services/com.sun.mirror.apt.AnnotationProcessorFactory
-------------------------------------------------------------------------------------------------
annotation.FooAnnotationProcessorFactory

==========================================
build.xml
------------
<!-- run using Java 6 U3 -->
<project name="sample" default="build">
    <property environment="env"/>
    <target name="build">
        <mkdir dir="processor-bin" />
        <javac destdir="processor-bin" srcdir="src" includes="annotation/*.java"/>
        <copy todir="processor-bin">
            <fileset dir="src" includes="META-INF/**" />
        </copy>
        <mkdir dir="generated" />
        <exec executable="${env.JAVA_HOME}/bin/apt.exe" failonerror="true" >
            <arg value="-classpath"/>
            <arg value="processor-bin"/>
            <arg value="-nocompile"/>
            <arg value="-s"/>
            <arg value="generated"/>
            <arg value="src/a/b/c/Sample.java"/>
        </exec>
    </target>
</project>



---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
I tracked the problem down by disabling my annotation processors; the javac step in my compile caught the problem.

Removing the offending comma allowed my code to build properly.

Comments
EVALUATION The Foo and Fee annotation types and the annotation in sample "@Foo(fees = {@Fee(name = "aaa"),})" are all legal according to the JLS. In JLSv3 9.7 Annotations http://java.sun.com/docs/books/jls/third_edition/html/interfaces.html#9.7 a trailing comma is explicitly allowed in this case: ElementValueArrayInitializer: { ElementValuesopt ,opt } This issue is caussed by javac bug 6337964 and is being closed as a duplicate accordingly.
22-09-2009

EVALUATION Will investigate.
03-03-2008