1

I programmed an interface for a very simple webserver in Java that allows the user to put his own jar-archives into a folder, and when the server starts, they will be loaded.

In that archive is a text file which defines the main class etc., but my plugin loader only loads the class defined in the file. So, when I use a second class and want to access it (Example e = new Example() ), it will result in a NoClassDefFoundError-Exception:

Exception in thread "main" java.lang.NoClassDefFoundError: de/Ercksen/WebserverPlugin/Plugin/WasWillstDu
at de.Ercksen.WebserverPlugin.Plugin.MainPlugin.onEnable(MainPlugin.java:17)
at de.Ercksen.Webserver.Webserver.initPlugins(Webserver.java:236)
at de.Ercksen.Webserver.Webserver.loadPlugins(Webserver.java:231)
at de.Ercksen.Webserver.Webserver.execute(Webserver.java:37)
at de.Ercksen.Webserver.Webserver.main(Webserver.java:30)
    Caused by: java.lang.ClassNotFoundException:
    Ercksen.WebserverPlugin.Plugin.WasWillstDu
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 5 more

Is there a method or something that can simply load all the classes in the .jar-archive? Or any other ideas?

My class loader:

@SuppressWarnings("unchecked")
public static Class<? extends Plugin> loadPluginClass(File file, String path) throws ClassNotFoundException, ClassCastException, IOException {
    URLClassLoader loader = new URLClassLoader(new URL[] {file.toURI().toURL()});
    Class<?> c = loader.loadClass(path);
    loader.close();
    return (Class<? extends Plugin>) c;
}
Ercksen
  • 668
  • 9
  • 23
  • What is the purpose of what you're trying to accomplish? There are a few ways this might be done, and the best option will depend on your goal. – chrylis -cautiouslyoptimistic- Dec 20 '13 at 20:39
  • But the ideas are missing ;) is there a method to get an array of all the classes in a package? Then they could be loaded manually in a for-loop...? – Ercksen Dec 20 '13 at 20:43
  • Loading a Jar into UrlClassLoader should enable the loading of all classes inside the jar, have you tried to use the same classloader that already loaded the first class or have you created a new instance? It further seems that you didn't specify a valid fully qualified classname - try to replace `/` with `.`. If this still does not solve your problem you might try to [iterate through the content of the jar file](http://stackoverflow.com/questions/20586067/how-to-load-unknown-class-from-downloaded-jar-file-during-runtime/20586806#20586806) and extract the classnames manually – Roman Vottner Dec 20 '13 at 21:40
  • Moreover, what you are trying to achieve sounds a bit similar to one of the tasks I had for a university course a couple of years ago. Instead of a plain-text file I used the `MANIFEST.MF` file inside the jar to specify the plugin class which should be loaded (and all its dependencies). Maybe there is [something useful](https://github.com/RovoMe/PluginApplication) for you in there. PS: OK, had a second look on your code - the fully qualified classname should not be the problem, but maybe the closing of the classloader - at this point it has not instantiated the class or loaded its dependencies – Roman Vottner Dec 20 '13 at 21:54
  • and you seem to load every single class of the jar from a different instance of the classloader - this further means that those types are incompatible to each other (you can't cast one object to the other) : say you load class E with instance 1 and a further class E (can be the same, even the bytes) with instance 2, then both classes will be incompatible as they got loaded with different classloaders. This holds true for a class D which has a reference (field) to class E but was loaded with a different instance of the classloader than E. – Roman Vottner Dec 20 '13 at 21:58
  • What about other resources in the jar that the plugin might need, like properties files? – Adriaan Koster Dec 20 '13 at 22:20
  • @Roman Thanks for all your tips, the next thing I will try is sharing the main classe's class loader, that everything ins loaded with the same... – Ercksen Dec 21 '13 at 08:16
  • @Adriaan they are all in the plugin.txt file – Ercksen Dec 21 '13 at 08:18
  • @Ercksen One further suggestion: instead of instantiating a UrlClassLoader via the `new` operator, you can also try to use `UrlClassLoader.newInstance(URL[], parentClassLoader)` and create a class object via `Class.forName(fullyQualifiedClassNameAsString, true, loader);`. The `true`-parameter defines that a class needs to be initialized. – Roman Vottner Dec 21 '13 at 10:00
  • @Roman Hmm, the last two uptions don't work, but maybee the problem is another. Maybee I should inform more about the ClassLoader, but I created a test plugin that has uses a single file, but there are two classes in it. But it's not working (Same stack trace). The plugin can be seen here: http://ms589.nitrado.net:1648/public/TestPlugin.java The error only occurs only when calling Test.print(); – Ercksen Dec 21 '13 at 10:52
  • @Ercksen Your posted error states that it can't find `Ercksen.WebserverPlugin.Plugin.WasWillstDu` but your TestPlugin example does not even include `WasWillstDu` - maybe you used a wrong package or a wrong classname? And before chatting to much here, I suggest you mail me (even in German as WasWillstDu seems German to me ;)) so we can figure out why your classloading does not work. Just use the first to letters of my first name and the first to letters of my last name AT gmx.at – Roman Vottner Dec 21 '13 at 11:08
  • @RomanVottner Ok, the mail has been written! I hope, the information is enough – Ercksen Dec 21 '13 at 12:26

0 Answers0