-3

I have been working on a quite complex project for a while. It involves 2 Modules, net.lightbluefoxlabs.dev.multirealm.core.multirealmcore and net.lbflabs.dev.realms.survivalrealm, where the first has an abstract class which in itself is derived from another class (Maybe this is the issue?). When trying to create a service for the class, I get this error: java.util.ServiceConfigurationError: net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.LoadedRealmPlugin: net.lbflabs.dev.realms.survivalrealm.SurvivalRealm not a subtype even though it does actually extends the correct class. Here is the code loading the service:

File file = new File("Dir/plugin_jar.jar");
URLClassLoader c = new URLClassLoader(new URL[]{file.getAbsoluteFile().toURI().toURL()});
ServiceLoader<LoadedRealmPlugin> loader = ServiceLoader.load(LoadedRealmPlugin.class, c);
LoadedRealmPlugin p = loader.iterator().next(); // Throws the exception
return p;

I have simplified the class and packet/module names since my project is already quite big and I do not think it is necessary. If you need any additional info, please ask.

Edit: Stacktrace

[13:08:24] [Thread-9/WARN]: Exception in thread "Thread-9" java.util.ServiceConfigurationError: net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.LoadedRealmPlugin: net.lbflabs.dev.realms.survivalrealm.SurvivalRealm not a subtype
[13:08:24] [Thread-9/WARN]:     at java.base/java.util.ServiceLoader.fail(Unknown Source)
[13:08:24] [Thread-9/WARN]:     at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(Unknown Source)
[13:08:24] [Thread-9/WARN]:     at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(Unknown Source)
[13:08:24] [Thread-9/WARN]:     at java.base/java.util.ServiceLoader$2.next(Unknown Source)
[13:08:24] [Thread-9/WARN]:     at java.base/java.util.ServiceLoader$2.next(Unknown Source)
[13:08:24] [Thread-9/WARN]:     at java.base/java.util.ServiceLoader$3.next(Unknown Source)
[13:08:24] [Thread-9/WARN]:     at net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.LoadedRealmPlugin.RealmFactory(LoadedRealmPlugin.java:22)
[13:08:24] [Thread-9/WARN]:     at net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.LoadedRealmPlugin.RealmFactory(LoadedRealmPlugin.java:32)
[13:08:24] [Thread-9/WARN]:     at net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.UnloadedRealm.GetLoadedRealm(UnloadedRealm.java:25)
[13:08:24] [Thread-9/WARN]:     at net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.UnloadedRealm.Load(UnloadedRealm.java:39)
[13:08:24] [Thread-9/WARN]:     at net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.RealmBase.Initialize(RealmBase.java:33)
[13:08:24] [Thread-9/WARN]:     at net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.RealmBase.<init>(RealmBase.java:25)
[13:08:24] [Thread-9/WARN]:     at net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.UnloadedRealm.<init>(UnloadedRealm.java:18)
[13:08:24] [Thread-9/WARN]:     at net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.RealmManager.Initialize(RealmManager.java:25)
[13:08:24] [Thread-9/WARN]:     at net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.RealmManager.lambda$InitializeAsync$0(RealmManager.java:42)
[13:08:24] [Thread-9/WARN]:     at java.base/java.lang.Thread.run(Unknown Source)

Note that A.ServiceTemplate is net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.LoadedRealmPlugin and B.ServiceProvider is net.lbflabs.dev.realms.survivalrealm.SurvivalRealm

Jakob Tinhofer
  • 313
  • 3
  • 16
  • What's the full stack trace of the exception? – tgdavies Dec 21 '20 at 12:30
  • In your first paragraph you talk about A.ServiceTemplate and B.ServiceProvider. In your last paragraph about A.ServiceProvider and B.Service. Please fix your question, and add code which shows the actual declarations of net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.LoadedRealmPlugin and net.lbflabs.dev.realms.survivalrealm.SurvivalRealm – tgdavies Dec 21 '20 at 13:02
  • You aren't passing classloaders, leading to a same class in different class loaders. As class identity is based on class and classloader things start to fail. – M. Deinum Dec 21 '20 at 13:06
  • Hi @M.Deinum, since I am new to this, could you maybe explain a bit closer? Also, you could put it down as an answer so I can later accept it if it fixes my issue – Jakob Tinhofer Dec 21 '20 at 19:40
  • Sorry, I really did not notice I messed up the names. I now just replaced everything with the longer packet names. Thanks for pointing it out! – Jakob Tinhofer Dec 21 '20 at 19:41

1 Answers1

2

Class identity is based on the FQN of the class and the ClassLoader it is being loaded in.

So the class net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.LoadedRealmPlugin loaded in classloader 1 is a different class then net.lightbluefoxlabs.dev.multirealm.core.multirealmcore.Realms.LoadedRealmPlugin loaded in classloader 2. You will get classcast exceptions or not a subtype exception simply because they aren't the same (from the pov of the JVM).

As mentioned in the other question regarding the construction of your own ClassLoader you should pass a parent ClassLoader. This ClassLoader should have the shared classes as to allow proper hierarchies of classes to be constructed.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224