samedi 22 février 2020

ClassNotFoundException although class exists and is loaded

I am building a modular application which contains template classes in its core module (executed by the user) and loads implementations for these classes from .jar files in a certain directory on every startup.

The loading process of these implementations looks like this:

Collection<Class<?>> output = Lists.newArrayList();
JarFile jarFile = new JarFile(path);
Enumeration<JarEntry> jarEntries = jarFile.entries();

URL[] urls = { new URL("jar:file:" + path + "!/") };
URLClassLoader classLoader = URLClassLoader.newInstance(urls);

while (jarEntries.hasMoreElements()) {
  JarEntry jarEntry = jarEntries.nextElement();
  if(jarEntry == null
          || jarEntry.isDirectory()
          || !jarEntry.getName().endsWith(".class")){
    continue;
  }

  ...

  int ignoreClass = ".class".length();
  String className = jarEntry.getName().substring(0,jarEntry.getName().length()-ignoreClass);
  className = className.replace('/', '.');

  Class implementationClass = classLoader.loadClass(className);
  Class<?> outputClass = this.loadToClassPath(path, implementationClass);
  output.add(outputClass);
  continue;

}


private Class<?> loadToClassPath(String path, Class toLoad) throws NoSuchMethodException,
      MalformedURLException,
      InvocationTargetException,
      IllegalAccessException,
      ClassNotFoundException {
  URLClassLoader loader = (URLClassLoader) KelpApplicationRepository.class.getClassLoader();
  Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
  addURL.setAccessible(true);
  addURL.invoke(loader, new File(path).toURI().toURL());
  return loader.loadClass(toLoad.getName());
}

It compiles, but I get the following runtime error:

[17:51:24 ERROR]: de/pxav/kelp/core/sidebar/version/SidebarVersionTemplate initializing Kelp v0.1-SNAPSHOT (Is it up to date?)
java.lang.NoClassDefFoundError: de/pxav/kelp/core/sidebar/version/SidebarVersionTemplate
    at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_171]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[?:1.8.0_171]
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[?:1.8.0_171]
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[?:1.8.0_171]
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[?:1.8.0_171]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[?:1.8.0_171]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[?:1.8.0_171]
    at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_171]
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[?:1.8.0_171]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_171]
    at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:814) ~[?:1.8.0_171]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_171]
    at de.pxav.kelp.core.application.inject.VersionBinderModule.implementationsOf(VersionBinderModule.java:214) ~[?:?]
    at de.pxav.kelp.core.application.inject.VersionBinderModule.lambda$configure$1(VersionBinderModule.java:75) ~[?:?]
    at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[?:1.8.0_171]
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[?:1.8.0_171]
    at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) ~[?:1.8.0_171]
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[?:1.8.0_171]
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[?:1.8.0_171]
    at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[?:1.8.0_171]
    at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[?:1.8.0_171]
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_171]
    at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) ~[?:1.8.0_171]
    at de.pxav.kelp.core.application.inject.VersionBinderModule.configure(VersionBinderModule.java:73) ~[?:?]
    at com.google.inject.AbstractModule.configure(AbstractModule.java:62) ~[?:?]
    at com.google.inject.spi.Elements$RecordingBinder.install(Elements.java:340) ~[?:?]
    at com.google.inject.spi.Elements.getElements(Elements.java:110) ~[?:?]
    at com.google.inject.internal.InjectorShell$Builder.build(InjectorShell.java:138) ~[?:?]
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:104) ~[?:?]
    at com.google.inject.Guice.createInjector(Guice.java:96) ~[?:?]
    at com.google.inject.Guice.createInjector(Guice.java:73) ~[?:?]
    at com.google.inject.Guice.createInjector(Guice.java:62) ~[?:?]
    at de.pxav.kelp.core.KelpPlugin.onLoad(KelpPlugin.java:41) ~[?:?]
    at org.bukkit.craftbukkit.v1_8_R3.CraftServer.loadPlugins(CraftServer.java:297) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at org.bukkit.craftbukkit.v1_8_R3.CraftServer.reload(CraftServer.java:739) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at org.bukkit.Bukkit.reload(Bukkit.java:535) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:25) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchCommand(CraftServer.java:641) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at org.bukkit.craftbukkit.v1_8_R3.CraftServer.dispatchServerCommand(CraftServer.java:627) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.DedicatedServer.aO(DedicatedServer.java:412) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.DedicatedServer.B(DedicatedServer.java:375) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.MinecraftServer.A(MinecraftServer.java:654) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:557) [spigot.jar:git-Spigot-db6de12-18fbb24]
    at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]
Caused by: java.lang.ClassNotFoundException: de.pxav.kelp.core.sidebar.version.SidebarVersionTemplate
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[?:1.8.0_171]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[?:1.8.0_171]
    at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:814) ~[?:1.8.0_171]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[?:1.8.0_171]
    ... 45 more

I am wondering why, because the .class file of SidebarVersionTemplate exists in the core module. Maybe it has to do with the extends keyword in the implementation class? Does this keyword load classes by default in Java?

implementation class:

public class SidebarVersion extends SidebarVersionTemplate {

template class:

public abstract class SidebarVersionTemplate {

Any ideas? Thanks in advance





Aucun commentaire:

Enregistrer un commentaire