NoClassDefFound trying to test for a custom annotation

Hello, I am trying to check if a plugin contains my custom annotation I have created. Here is the code I use:

for(PluginContainer pluginC : Sponge.getPluginManager().getPlugins()) {
  if(pluginC.getInstance().isPresent()) {
    if(pluginC.getInstance().get().getClass().isAnnotationPresent(MyAnnotation.class)) {//<-- Error here
      System.out.println("Yay!");
    }
  }
}

What could be going wrong?

Could you post your annotation class and the full stack trace? The first thing that comes to mind is that you don’t have your retention policy set to runtime. Unless you add @Retention(RetentionPolicy.RUNTIME) to your annotation class, the compiler will discard your annotation.

As @windy said, the only way we can really help is by seeing the stack trace. (Also, regardless of retention policy, the annotation class itself should still exist, as retention policy dictates retaining information about classes/fields/others annotated with the annotation. So NoClassDefFound doesn’t particularly make sense.)

1 Like

Stack Trace: http://pastebin.com/b6H9NeUC

The annotation has a retention policy of runtime.


EDIT: I am using the ‘export’ function of Eclipse to build the JAR. It works perfectly for other plugins, but for some reason not this one.

Have you tried opening your jar file with an archive utility program and checking to see if the class has actually been included in the jar?

I had thought of this but I wasn’t sure if the compiler removed the class entirely or only appearances of it. Good to know.

Actually, the reference to the class (i.e. the annotation) is the only thing not removed with the retention policy. The class itself may or may not exist at runtime, causing this NoClassDefFound.

I would advise you to use a build system of some sort, as the Export function in Eclipse doesn’t work as expected every time.

@windy @kenzierocks

Thanks, I’ll try using a build system later. I have checked previously and the class is in the JAR, so I don’t why I get a ClassNotFoundException. The class is definitely in there.

EDIT: I’ve tried a build system but the same error occurs.

I get the feeling it might be a class loader issue? I’d have to test this for myself to know for sure.

Have you specified the plugin containing the annotation class as a dependency in the plugin annotated with it?
Could be that the plugin using the annotation is being loaded before the plugin containing the annotation class has been added to the classpath.

@dags

I do the testing on the ServerStartedEvent, so every plugin should be loaded.

@simon816

Why is this issue occurring/how do I fix it?


I have a strange discovery that I made. The code throws the ClassNotFoundException when I make my class like this (Note this is a demo class and will not function):

@CustomAnnotation(varOne = "hi", varTwo = "bye", varThree = "hello")
public class MainClass {
  //Error!
  for(PluginContainer pluginC : Sponge.getPluginManager().getPlugins()) {
    if(pluginC.getInstance().isPresent()) {
      if(pluginC.getInstance().get().getClass().isAnnotationPresent(CustomAnnotation.class)) {
        System.out.println("Yay!");
      }
    }
  }

}

But, if I remove the testing code, and just annotate my class with the annotation I don’t get an exception.


@CustomAnnotation(varOne = "hi", varTwo = "bye", varThree = "hello")
public class MainClass {
  //No error!
}

The error seems to only occur when using the code CustomAnnotation.class


Here is my annotation code:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CustomAnnotation {
	
	String varOne();
	
	String varTwo();
	
	String varThree();
}

UPDATE: I have found that annotating the class the test code is in works 100% with 0 errors. However, when an external plugin is annotated the testing code (See the original post for the code) fails with the ClassNotFoundException.

Sure, but if the class doesn’t exist at the time the plugin is loaded then you’re going to have a bad time.

As a quick test, try rename the plugin that contains the annotation class such that it comes alphabetically before the other plugin - it should load first (on windows at-least) and resolve the error.

edit: just to be clear to others with this issue, renaming the jar isn’t the fix. You need to properly define your plugin’s ‘dependencies’ string so that it loads after the plugin containing the annotation/interface/whatever, that you’re relying on.

Thank you! It works now with no errors!