-
Bug
-
Resolution: Fixed
-
P3
-
7u45
-
b02
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8045111 | 8u25 | Jan Lahoda | P3 | Resolved | Fixed | b01 |
JDK-8033136 | 8u20 | Jan Lahoda | P3 | Resolved | Fixed | b01 |
JDK-8052550 | emb-8u26 | Jan Lahoda | P3 | Resolved | Fixed | b17 |
FULL PRODUCT VERSION :
On the Mac:
bash-3.2$ java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
bash-3.2$ javac -version
javac 1.7.0_45
On the Linux
bash-3.2$ java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
bash-3.2$ javac -version
javac 1.7.0_45
ADDITIONAL OS VERSION INFORMATION :
Linux desktop 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
Darwin laptop 12.5.0 Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 x86_64
A DESCRIPTION OF THE PROBLEM :
I declare an annotation processor as follows:
@SupportedAnnotationTypes({ "ExistingAnnotation"})
public class DemoAnnotationProcessor extends AbstractProcessor {
../..
}
In the process method [1] inside this processor, the resolution of the annotated elements is inconsistent. Here is the code being used:
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(ExistingAnnotation.class);
When there are missing dependencies for the compilation, which would cause an "error: cannot find symbol" later, the set of annotatedElements improperly contains all such unresolved annotations, in addition to the properly annotated elements.
This is a change in behavior from JDK6. It causes confusing problems when the annotation processing step is used only for code generation (because there is no message explaining the lacking types if the annotation processing step throws an exception), and contradicts what getElementsAnnotatedWith() [2] is supposed to do.
[1] http://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/Processor.html#process%28java.util.Set,%20javax.annotation.processing.RoundEnvironment%29
[2] http://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/RoundEnvironment.html#getElementsAnnotatedWith%28javax.lang.model.element.TypeElement%29
REGRESSION. Last worked in version 6u45
ADDITIONAL REGRESSION INFORMATION:
Where the failure does not repro:
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Here are the three files for the repro. Instructions at the end
-----ExistingAnnotation.java ------
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExistingAnnotation {}
-----------------------------------
-------HelloWorld.java ------
@ExistingAnnotation
public class HelloWorld{
@UnexistingAnnotation
String someField;
public static void main(String args[]){
System.out.println("Hello, world.");
}
}
---------------------------
-------DemoAnnotationProcessor.java-------
import java.util.HashSet;
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.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic.Kind;
import javax.tools.JavaFileObject;
@SupportedAnnotationTypes({ "ExistingAnnotation"})
public class DemoAnnotationProcessor extends AbstractProcessor {
/**
* Whether the mirror Element e is annotated with an annotation whose class is c
* @param e
* @param c
* @return
*/
private boolean isAnnotatedWith(Element element, Class<?> c){
for(AnnotationMirror a: element.getAnnotationMirrors()){
Elements elements = processingEnv.getElementUtils();
TypeElement activitiesTypeElement = elements.getTypeElement(c.getCanonicalName());
if(a.getAnnotationType().asElement().equals(activitiesTypeElement))
return true;
}
return false;
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!roundEnv.processingOver()) {
processingEnv.getMessager().printMessage(Kind.NOTE, "DemoAnnotationProcessor.process() invoked.");
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(ExistingAnnotation.class);
for (Element annotatedElement : annotatedElements) {
if( ! isAnnotatedWith(annotatedElement, ExistingAnnotation.class)){
processingEnv.getMessager().printMessage(Kind.ERROR, "This element " + annotatedElement + " is not annotated with " + ExistingAnnotation.class);
continue;
}
}
}
else {
processingEnv.getMessager().printMessage(Kind.NOTE, "Processing finished");
}
return false;
}
}
------------------------
# set path to use JDK 7
javac ExistingAnnotation.java
javac DemoAnnotationProcessor.java
bash-3.2$ javac -processorpath . -processor DemoAnnotationProcessor -proc:only HelloWorld.java
HelloWorld.java:4: error: cannot find symbol
@UnexistingAnnotation
^
symbol: class UnexistingAnnotation
location: class HelloWorld
warning: No SupportedSourceVersion annotation found on DemoAnnotationProcessor, returning RELEASE_6.
warning: Supported source version 'RELEASE_6' from annotation processor 'DemoAnnotationProcessor' less than -source '1.7'
Note: DemoAnnotationProcessor.process() invoked.
error: This element someField is not annotated with interface ExistingAnnotation
HelloWorld.java:4: error: cannot find symbol
@UnexistingAnnotation
^
symbol: class UnexistingAnnotation
location: class HelloWorld
Note: Processing finished
2 errors
2 warnings
Note the error reported by the annotation processor.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The expected result is that the annotation processor would not return an error, because calling getElementsAnnotatedWith on the environment would only return the proper elements.
ACTUAL -
Note the error reported in "steps to reproduce".
According to my testing, all the annotations that can not be resolved to a type are returned by getElementsAnnotatedWith.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
The code is included in "steps to reproduce" above.
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Make sure all the annotation types are defined.
On the Mac:
bash-3.2$ java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
bash-3.2$ javac -version
javac 1.7.0_45
On the Linux
bash-3.2$ java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
bash-3.2$ javac -version
javac 1.7.0_45
ADDITIONAL OS VERSION INFORMATION :
Linux desktop 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
Darwin laptop 12.5.0 Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 x86_64
A DESCRIPTION OF THE PROBLEM :
I declare an annotation processor as follows:
@SupportedAnnotationTypes({ "ExistingAnnotation"})
public class DemoAnnotationProcessor extends AbstractProcessor {
../..
}
In the process method [1] inside this processor, the resolution of the annotated elements is inconsistent. Here is the code being used:
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(ExistingAnnotation.class);
When there are missing dependencies for the compilation, which would cause an "error: cannot find symbol" later, the set of annotatedElements improperly contains all such unresolved annotations, in addition to the properly annotated elements.
This is a change in behavior from JDK6. It causes confusing problems when the annotation processing step is used only for code generation (because there is no message explaining the lacking types if the annotation processing step throws an exception), and contradicts what getElementsAnnotatedWith() [2] is supposed to do.
[1] http://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/Processor.html#process%28java.util.Set,%20javax.annotation.processing.RoundEnvironment%29
[2] http://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/RoundEnvironment.html#getElementsAnnotatedWith%28javax.lang.model.element.TypeElement%29
REGRESSION. Last worked in version 6u45
ADDITIONAL REGRESSION INFORMATION:
Where the failure does not repro:
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Here are the three files for the repro. Instructions at the end
-----ExistingAnnotation.java ------
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExistingAnnotation {}
-----------------------------------
-------HelloWorld.java ------
@ExistingAnnotation
public class HelloWorld{
@UnexistingAnnotation
String someField;
public static void main(String args[]){
System.out.println("Hello, world.");
}
}
---------------------------
-------DemoAnnotationProcessor.java-------
import java.util.HashSet;
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.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic.Kind;
import javax.tools.JavaFileObject;
@SupportedAnnotationTypes({ "ExistingAnnotation"})
public class DemoAnnotationProcessor extends AbstractProcessor {
/**
* Whether the mirror Element e is annotated with an annotation whose class is c
* @param e
* @param c
* @return
*/
private boolean isAnnotatedWith(Element element, Class<?> c){
for(AnnotationMirror a: element.getAnnotationMirrors()){
Elements elements = processingEnv.getElementUtils();
TypeElement activitiesTypeElement = elements.getTypeElement(c.getCanonicalName());
if(a.getAnnotationType().asElement().equals(activitiesTypeElement))
return true;
}
return false;
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!roundEnv.processingOver()) {
processingEnv.getMessager().printMessage(Kind.NOTE, "DemoAnnotationProcessor.process() invoked.");
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(ExistingAnnotation.class);
for (Element annotatedElement : annotatedElements) {
if( ! isAnnotatedWith(annotatedElement, ExistingAnnotation.class)){
processingEnv.getMessager().printMessage(Kind.ERROR, "This element " + annotatedElement + " is not annotated with " + ExistingAnnotation.class);
continue;
}
}
}
else {
processingEnv.getMessager().printMessage(Kind.NOTE, "Processing finished");
}
return false;
}
}
------------------------
# set path to use JDK 7
javac ExistingAnnotation.java
javac DemoAnnotationProcessor.java
bash-3.2$ javac -processorpath . -processor DemoAnnotationProcessor -proc:only HelloWorld.java
HelloWorld.java:4: error: cannot find symbol
@UnexistingAnnotation
^
symbol: class UnexistingAnnotation
location: class HelloWorld
warning: No SupportedSourceVersion annotation found on DemoAnnotationProcessor, returning RELEASE_6.
warning: Supported source version 'RELEASE_6' from annotation processor 'DemoAnnotationProcessor' less than -source '1.7'
Note: DemoAnnotationProcessor.process() invoked.
error: This element someField is not annotated with interface ExistingAnnotation
HelloWorld.java:4: error: cannot find symbol
@UnexistingAnnotation
^
symbol: class UnexistingAnnotation
location: class HelloWorld
Note: Processing finished
2 errors
2 warnings
Note the error reported by the annotation processor.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The expected result is that the annotation processor would not return an error, because calling getElementsAnnotatedWith on the environment would only return the proper elements.
ACTUAL -
Note the error reported in "steps to reproduce".
According to my testing, all the annotations that can not be resolved to a type are returned by getElementsAnnotatedWith.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
The code is included in "steps to reproduce" above.
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Make sure all the annotation types are defined.
- backported by
-
JDK-8033136 RoundEnvironment.getElementsAnnotatedWith receives wrong elements
-
- Resolved
-
-
JDK-8045111 RoundEnvironment.getElementsAnnotatedWith receives wrong elements
-
- Resolved
-
-
JDK-8052550 RoundEnvironment.getElementsAnnotatedWith receives wrong elements
-
- Resolved
-
- relates to
-
JDK-6498938 Faulty comparison of TypeMirror objects in RoundEnvironment.getElementsAnnotatedWith implementation
-
- Closed
-
-
JDK-8039079 Test tools/javac/processing/environment/round/TestElementsAnnotatedWith.java fails
-
- Closed
-