javachecker-framework

Why are annotations added by checker framework needed at runtime?


I'm using Checker Framework via the maven-compiler-plugin. The resulting bytecode has annotations in fields such as org.checkerframework.checker.nullness.qual.NonNull or org.checkerframework.checker.nullness.qual.UnknownKeyFor that were not there in the source code. These qual annotations have @Retention(RetentionPolicy.RUNTIME).
My understanding is that checker framework works at compile time. Why are those annotations added to the bytecode then retained at runtime? is it standard practice to leave the annotations in production artefacts? because this means I will need to add qual to the runtime classpath, which sounds like an unnecessary cost/risk given that this is all about build time checks. Without that qual jar, libraries that introspect field annotations, like hibernate-validator, throw NPEs:

Caused by: java.lang.NullPointerException
    at sun.reflect.annotation.TypeAnnotationParser.mapTypeAnnotations(TypeAnnotationParser.java:356)
    at sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl.<init>(AnnotatedTypeFactory.java:139)
    at sun.reflect.annotation.AnnotatedTypeFactory.buildAnnotatedType(AnnotatedTypeFactory.java:65)
    at sun.reflect.annotation.TypeAnnotationParser.buildAnnotatedType(TypeAnnotationParser.java:79)
    at java.lang.reflect.Field.getAnnotatedType(Field.java:1177)

Solution

  • The Checker Framework manual contains the following FAQ: Why are type annotations declared with @Retention(RetentionPolicy.RUNTIME)?

    If you are using a tool that NPEs as a result of a missing annotation, that is a buggy tool. Such a situation is not uncomon; for example, the JVM won't crash if it cannot find an annotation that is mentioned in a class file that it is running.