Why doesn't a missing annotation cause a ClassNotFoundException at runtime?

Viewed 14392

Consider the following code:

A.java:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@interface A{}

C.java:

import java.util.*;

@A public class C {
        public static void main(String[] args){
                System.out.println(Arrays.toString(C.class.getAnnotations()));
        }
}

Compiling and running works as expected:

$ javac *.java
$ java -cp . C
[@A()]

But then consider this:

$ rm A.class
$ java -cp . C
[]

I would've expected it to throw a ClassNotFoundException, since @A is missing. But instead, it silently drops the annotation.

Is this behaviour documented in the JLS somewhere, or is it a quirk of Sun's JVM? What's the rationale for it?

It seems convenient for things like javax.annotation.Nonnull (which seems like it should've been @Retention(CLASS) anyway), but for many other annotations it seems like it could cause various bad things to happen at runtime.

3 Answers
Related