Specification of behavior when annotation missing from classpath is attached to a class

Ivan G. :

I am looking for a specification of what the behavior will be when a Java class is annotated with an annotation that is not present on the consumer's classpath. Specifically, when the annotated class is packaged as a jar and pulled in to another project (in Maven terms, an 'optional' or 'provided' dependency contains the annotation and the dependent elects not to depend on that).

I found an old Eclipse bug thread that mentions this: https://bugs.eclipse.org/bugs/show_bug.cgi?id=320965

My understanding is that annotations are supposed to be dropped from the class file if the annotation class isn't present.

I have observed the same behavior; that is, the class seems to load fine when the annotation is not found, but I cannot find this specified anywhere. I'm using OpenJDK.

(For those curious, the context is making a library dependency injection-friendly without tying it to a specific DI framework, so I'd like to use both CDI annotations and Guice annotations, for example, but consumers will probably not want to bring in both sets of annotations, if any at all)

Florian Weimer :

Neither the Java Language Specification nor the Java Virtual Machine Specification covers this directly. The latter does not discuss annotations for verification or linking, so one could argue that missing annotation types should not cause a class loading failure. The JDK API documentation does not discuss this, except for missing classes in class-valued annotations. That looks like an omission.

The parser for user-defined (non-VM) annotations lives in sun.reflect.annotation.AnnotationParser. As you can see, unknown annotations are simply skipped:

try {
    try {
        sig = constPool.getUTF8At(typeIndex);
        annotationClass = (Class<? extends Annotation>)parseSig(sig, container);
    } catch (IllegalArgumentException ex) {
        // support obsolete early jsr175 format class files
        annotationClass = (Class<? extends Annotation>)constPool.getClassAt(typeIndex);
    }
} catch (NoClassDefFoundError e) {
    if (exceptionOnMissingAnnotationClass)
        // note: at this point sig is "[unknown]" or VM-style
        // name instead of a binary name
        throw new TypeNotPresentException(sig, e);
    skipAnnotation(buf, false);
    return null;
}

There is also no way to detect that this happens. As a result, if you want to make sure that there are no unknown annotations present, you have to parse the class file with a different parser.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=156005&siteId=1