RFR 7183985: Class.getAnnotation() throws an ArrayStoreException when the annotation class not present

Joseph D. Darcy joe.darcy at oracle.com
Wed Feb 28 01:18:17 UTC 2018


Hi Liam,

On 2/24/2018 5:14 PM, Liam Miller-Cushon wrote:
> Hi, thanks for the comments.
>
> The updated webrev is at: 
> http://cr.openjdk.java.net/~cushon/7183985/webrev.02/ 
> <http://cr.openjdk.java.net/%7Ecushon/7183985/webrev.02/>
>
> On Fri, Feb 23, 2018 at 4:29 PM, Joseph D. Darcy <joe.darcy at oracle.com 
> <mailto:joe.darcy at oracle.com>> wrote:
>
>     Objects implementing the AnnotatedElement interface are also
>     created in javac during annotation processing. As a secondary
>     concern, it would be good to be have behavior between both javac
>     and runtime annotations consistent when possible. (My own to-do
>     list includes at least once such alignment JDK-8164819: "Make
>     javac's toString() on annotation objects consistent with core
>     reflection".)
>
>
> Do you have a pointer to where that happens? There's 
> javax.lang.model.AnnotatedConstruct#getAnnotation, which isn't 
> affected by this issue--it throws MirroredTypesExceptionProxy when 
> accessing an annotation value that is an array of class literals, 
> regardless of whether the elements' classes are missing. I'm not 
> seeing implementations of AnnotatedElement in langtools.

Sorry, I misremembered the situation in javac. For annotation processing 
in javac, AnnotatedElement is not a factor, but the class

src/jdk.compiler/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java

in javac does create annotation proxies, which is the same general 
technique used to create the annotation objects at runtime for core 
reflection.  These annotation objects in javac for javax.lang.model and 
annotation processing, do not follow the full contract of 
java.lang.reflect.AnnotatedElement. In particular, the annotations 
returned are not necessarily serializable. The intersection of methods 
on AnnotatedConstruct and AnnotatedElement is only a proper subset of 
the methods on AnnotatedElement; however, getAnnotation​(Class<T> 
annotationClass) is in the intersection.

>     Even in javac we've moved away from test and directory names based
>     on bugid. I'd recommend incorporating these regression tests into
>     the existing tests in
>         test/jdk/java/lang/annotation/Missing
>
>
> Thanks for the reminder, done.


I believe the new tests could reuse some of the existing types in 
test/jdk/java/lang/annotation/Missing. For example, the new 
MissingAnnotation.java is an alpha-rename of the existing Missing.java. 
If such sharing is not practical, then I'd recommend putting the new 
files into a subdirectory under underneath test/.../annotation/Missing 
(otherwise it will be confusing to edit these tests in the future since 
too many file names will start with "Missing".)

In MissingClassArrayElementTest.java:

   71     public static void main(String[] args) throws Exception {
   72         ClassArrayAnnotation[] outer = 
Test.class.getAnnotation(AnnotationAnnotation.class).value();
   73         // The second entry in the values array can be loaded 
successfully
   74         assertEquals(Arrays.toString(outer[1].value()), "[class 
java.lang.String]");

Something like

     assertEquals(Arrays.equals(outer[1].value(), {String.class})

would be more robust against any future changes in Class.toString. 
Likewise for the analogous comparisons.

>     It would be worth verifying whether or not this change also covers
>     java.lang.reflect.Executable.getParameterAnnotations(), more
>     specifically the implementation of that method in Method and
>     Constructor. The method getParameterAnnotations() is much less
>     used than getAnnotations and the other methods on the
>     AnnotatedElement interface, but still part of the annotations feature.
>
>
> Done.

Thanks.

Cheers,

-Joe


More information about the core-libs-dev mailing list