Unknown annotations are not ignored in Class.getAnnotations on Android Jelly Bean

Viewed 432

Problem

According to JSR-175 java specification if annotation is not available in the runtime it should be silently ignored. But on Android API 15-16 calling getDeclaredAnnotations() causes NoClassDefFoundError exception. On API 17+ it is working as expected without exception.

Check example project below for details.

Question

What workaround would you suggest? Do you know about the related Android bug report? I couldn't find one.

Example

We have a sample class with @Nullable annotation:

public class SampleClass {
   @Nullable
   private String _content;
}

@Nullable is available during the build process, but we exclude it from the apk (to cut method count), in the example we do it like this:

configurations {
   provided
}

android.applicationVariants.all {
   variant -> variant.javaCompile.classpath += configurations.provided
}

dependencies {
   provided group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2'
}

In the MainActivity we try to get all annotations from the _content field:

Class clazz = SampleClass.class;
Field[] fields = clazz.getDeclaredFields();
Field field = clazz.getDeclaredField("_content"); 
Annotation[] annotations = field.getDeclaredAnnotations(); // this line is throwing exception on API 15-16

As a result we get and exception on Android API 15-16:

11-24 17:06:49.874 2146-2146/? E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.NoClassDefFoundError: javax/annotation/Nullable
        at java.lang.reflect.Field.getDeclaredAnnotations(Native Method)
        at java.lang.reflect.Field.getDeclaredAnnotations(Field.java:204)
        at im.getsocial.checkannotation.MainActivity.checkReflection(MainActivity.java:26)
        at im.getsocial.checkannotation.MainActivity.onCreate(MainActivity.java:15)
        at android.app.Activity.performCreate(Activity.java:5008)
        ...
    Caused by: java.lang.ClassNotFoundException: javax.annotation.Nullable
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
        at java.lang.reflect.Field.getDeclaredAnnotations(Native Method) 
        at java.lang.reflect.Field.getDeclaredAnnotations(Field.java:204) 
        at im.getsocial.checkannotation.MainActivity.checkReflection(MainActivity.java:26) 
        at im.getsocial.checkannotation.MainActivity.onCreate(MainActivity.java:15) 
        at android.app.Activity.performCreate(Activity.java:5008) 
        ...

The complete sample project is available here: http://take.ms/Li3NF

Interesting that Java 5 had similar issue reported: http://bugs.java.com/view_bug.do?bug_id=6322301

Updates

  • Jan 27: samplified example and fixed compile errors
0 Answers
Related