United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6322301 : unknown annotations are not ignored in Class.getAnnotations

Details
Type:
Bug
Submit Date:
2005-09-10
Status:
Closed
Updated Date:
2012-09-28
Project Name:
JDK
Resolved Date:
2005-11-01
Component:
core-libs
OS:
generic
Sub-Component:
java.lang:reflect
CPU:
generic
Priority:
P1
Resolution:
Fixed
Affected Versions:
5.0
Fixed Versions:
5.0u6 (b04)

Related Reports
Backport:
Relates:
Relates:
Relates:

Sub Tasks

Description
If I use Class.getAnnotations to discover all the annotations on a class,
and the class includes annotations that are unknown to the runtime (e.g.,
because the class was annotated with vendor-specific annotations for one
app server and is being deployed on another app server), I get an exception
and can't discover any of the annotations on the class.  According to the
JSR-175 spec lead, unknown annotations must be ignored by getAnnotations.

                                    

Comments
EVALUATION

I've reproduced the reported symptoms with a simple test case.  The stack trace for my test is

Exception in thread "main" java.lang.TypeNotPresentException: Type b.Bar not present
        at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:98)
        at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:107)
        at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:31)
        at sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:351)
        at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:175)
        at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
        at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
        at java.lang.Class.initAnnotationsIfNecessary(Class.java:3005)
        at java.lang.Class.getAnnotations(Class.java:2987)
        at Test.main(Test.java:10)
Caused by: java.lang.ClassNotFoundException: b.Bar
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:242)
        at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:95)

The proximal cause for this problem seems to be the method sun.reflect.annotation.AnnotationParser.parseAnnotation catching NoClassDefFoundError instead of TypeNotPresentException; the latter is thrown by the ParseSig.  At the bottom of the stack, sun.reflect.generics.factory.CoreReflectionFactory does a Class.forName on the name of the annotation in question, catches any ClassNotFoundException and throws a TypeNotPresentException instead.

Adding a catch block at least gets the simple test case to pass; with this change the core reflection and annotation regression tests still pass too.

More analysis will be needed to verify this fix is sufficient and correct.
                                     
2005-09-10
SUGGESTED FIX

src/share/classes/sun/reflect/annotation>sccs sccsdiff -r1.7 -r1.8 AnnotationParser.java

------- AnnotationParser.java -------
69c69
<             Annotation a = parseAnnotation(buf, constPool, container);
---
>           Annotation a = parseAnnotation(buf, constPool, container, false);
133c133
<                 Annotation a = parseAnnotation(buf, constPool, container);
---
>                 Annotation a = parseAnnotation(buf, constPool, container, false);
165a166,169
>      *
>      * @param exceptionOnMissingAnnotationClass if true, throw
>      * TypeNotPresentException if a referenced annotation type is not
>      * available at runtime
169c173,174
<                                               Class container) {
---
>                                               Class container,
>                                             boolean exceptionOnMissingAnnotationClass) {
171a177
>       String sig = "[unknown]";
174c180
<                 String sig = constPool.getUTF8At(typeIndex);
---
>                 sig = constPool.getUTF8At(typeIndex);
180a187,190
>           if (exceptionOnMissingAnnotationClass)
>               // note: at this point sig is "[unknown]" or VM-style
>               // name instead of a binary name
>               throw new TypeNotPresentException(sig, e);
183a194,199
>       catch (TypeNotPresentException e) {
>           if (exceptionOnMissingAnnotationClass)
>               throw e;
>             skipAnnotation(buf, false);
>             return null;
>         }
267c283
<               result = parseAnnotation(buf, constPool, container);
---
>               result = parseAnnotation(buf, constPool, container, true);
342a359,361
>         catch (TypeNotPresentException e) {
>             return new TypeNotPresentExceptionProxy(e.typeName(), e.getCause());
>         }
675c694
<                 result[i] = parseAnnotation(buf, constPool, container);
---
>                 result[i] = parseAnnotation(buf, constPool, container, true);
                                     
2006-01-20



Hardware and Software, Engineered to Work Together