JDK-7188605 : RoundEnvironment.getElementsAnnotatedWith misses @Inherited in JDK 6
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6u31
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: linux
  • CPU: x86
  • Submitted: 2012-08-02
  • Updated: 2012-08-14
  • Resolved: 2012-08-14
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_33"
Java(TM) SE Runtime Environment (build 1.6.0_33-b03)
Java HotSpot(TM) Server VM (build 20.8-b03, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux jglick-t520 3.2.0-27-generic-pae #43-Ubuntu SMP Fri Jul 6 15:06:05 UTC 2012 i686 i686 i386 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
The Javadoc of RoundEnvironment.getElementsAnnotatedWith specifies that the annotation "may appear directly or be inherited". Yet it seems that in JDK 6 this does not work; an element annotated only by inheritance is not produced. In JDK 7 it does work; the fix (if it can be identified as such) should be backported to a JDK 6 update.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached test case.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
JDK 7u5 produces:

warning: [options] bootstrap class path not set in conjunction with -source 1.6
getElementsAnnotatedWith(A): [p.Sub]
found by scanning only: p.Sub
1 warning
true

ACTUAL -
JDK 6u33 produces:

getElementsAnnotatedWith(A): []
found by scanning only: p.Sub
true


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

package pkg;
import java.io.File;
import java.io.FileWriter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Target;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementScanner6;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.ToolProvider;
public class Demo {
    @Target(ElementType.TYPE) @Inherited @interface A {}
    @A public static abstract class Supe {}
    public static void main(String[] args) throws Exception {
        File source = new File(System.getProperty("java.io.tmpdir"), "Sub.java");
        FileWriter w = new FileWriter(source);
        w.write("package p; public class Sub extends " + Supe.class.getCanonicalName() + " {}");
        w.flush();
        w.close();
        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
        List<String> opts = Arrays.asList("-source", "6", "-classpath", new File(Demo.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getAbsolutePath());
        CompilationTask task = javac.getTask(null, null, null, opts, null, javac.getStandardFileManager(null, null, null).getJavaFileObjects(source));
        task.setProcessors(Collections.singleton(new Proc()));
        System.out.println(task.call());
    }
    @SupportedSourceVersion(SourceVersion.RELEASE_6)
    @SupportedAnnotationTypes("pkg.Demo.A")
    private static class Proc extends AbstractProcessor {
        @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            if (roundEnv.processingOver()) {
                return false;
            }
            System.out.println("getElementsAnnotatedWith(A): " + roundEnv.getElementsAnnotatedWith(A.class));
            for (Element r : roundEnv.getRootElements()) {
                new ElementScanner6<Void,Void>() {
                    @Override public Void visitType(TypeElement e, Void p) {
                        if (e.getAnnotation(A.class) != null) {
                            System.out.println("found by scanning only: " + e);
                        }
                        return super.visitType(e, p);
                    }
                }.scan(r);
            }
            return true;
        }
    }
}

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

CUSTOMER SUBMITTED WORKAROUND :
Test case also shows the workaround: exhaustively search RoundEnvironment.getRootElements.

Comments
EVALUATION The issue is suspected as being fixed in JDK 7 as a consquence of 6498938. Since the EOL of the JDK 6 train is coming after only a handful of additional update releases, there are currently no plans to address this issue in JDK 6. Closing as will not fix.
14-08-2012