Compiler-Fehler NoClassDefFoundError beim Laden einer Class

The_F4nat1c

Mitglied
Ich versuche mit Hilfe eines URLClassLoaders eine bestimmte Klasse zu laden allerdings bekomme ich immer einen Fehler. Ich versuche eine Klasse aus einer anderen Jar zu laden dabei entsteht dann der Fehler.


Dies befindet sich in jar1
Code:
java.lang.NoClassDefFoundError: me/The_F4nAt1c/APC/Core/Modules/ModuleMain
    at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_181]
    at java.lang.ClassLoader.defineClass(Unknown Source) ~[?:1.8.0_181]
    at java.security.SecureClassLoader.defineClass(Unknown Source) ~[?:1.8.0_181]
    at java.net.URLClassLoader.defineClass(Unknown Source) ~[?:1.8.0_181]
    at java.net.URLClassLoader.access$100(Unknown Source) ~[?:1.8.0_181]
    at java.net.URLClassLoader$1.run(Unknown Source) ~[?:1.8.0_181]
    at java.net.URLClassLoader$1.run(Unknown Source) ~[?:1.8.0_181]
    at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_181]
    at java.net.URLClassLoader.findClass(Unknown Source) ~[?:1.8.0_181]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_181]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_181]
    at java.lang.Class.forName0(Native Method) ~[?:1.8.0_181]
    at java.lang.Class.forName(Unknown Source) ~[?:1.8.0_181]
    at me.The_F4nAt1c.APC.Core.Modules.ModuleValidator.precheck(ModuleValidator.java:47) ~[?:?]
    at me.The_F4nAt1c.APC.Core.Modules.ModuleLoader.loadModule(ModuleLoader.java:37) ~[?:?]
    at me.The_F4nAt1c.APC.Core.Modules.ModuleLoader.<clinit>(ModuleLoader.java:18) ~[?:?]
    at me.The_F4nAt1c.APC.Main.Initialization.OnLoad.<clinit>(OnLoad.java:39) ~[?:?]
    at me.The_F4nAt1c.APC.Main.APCore.onLoad(APCore.java:33) ~[?:?]
    at org.bukkit.craftbukkit.v1_12_R1.CraftServer.loadPlugins(CraftServer.java:310) [spigot.jar:git-Spigot-dcd1643-e60fc34]
    at net.minecraft.server.v1_12_R1.DedicatedServer.init(DedicatedServer.java:205) [spigot.jar:git-Spigot-dcd1643-e60fc34]
    at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:545) [spigot.jar:git-Spigot-dcd1643-e60fc34]
    at java.lang.Thread.run(Unknown Source) [?:1.8.0_181]
Caused by: java.lang.ClassNotFoundException: me.The_F4nAt1c.APC.Core.Modules.ModuleMain
    at java.net.URLClassLoader.findClass(Unknown Source) ~[?:1.8.0_181]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_181]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_181]


Ich lade die Class so:
Java:
ModuleDescription des = new ModuleDescription(f);
            this.description = des;
            f.delete();
            URLClassLoader mainLoader = new URLClassLoader(new URL[]{new URL("file:" + path)});

            //CHECK MAIN CLASS
            System.out.println(des.getMain());
            ModuleMain mainClass = (ModuleMain) Class.forName(des.getMain(), true, mainLoader).newInstance();


Dies befindet sich in JAR2:
Dies ist der Code aus der Class die ich laden möchte:
Java:
package de.test.module;

import me.The_F4nAt1c.APC.Core.Modules.ModuleMain;
import org.bukkit.Bukkit;

public class Mod extends ModuleMain {

    @Override
    public void onBeforePluginValidate() {
        Bukkit.getConsoleSender().sendMessage("§6TEST MODULE VALIDATION");
    }
}
 
Zuletzt bearbeitet:
Ich denke, das Problem wird sein, dass der URLClassLoader beim Laden der Klasse de.test.module.Main eben die Referenz auf die Superklasse `me.The_F4nAt1c.APC.Core.Modules.ModuleMain` auflösen will/muss, und weder der SystemClassLoader (welcher als Delegation ClassLoader bei der verwendeten Instanziierung des URLClassLoaders verwendet wird) noch der URLClassLoader diese ModuleMain Klasse kennt. Wie wird denn ModuleMain geladen/aufgelöst? Hast du da noch mehr ClassLoader am Start, auf die aber nicht delegiert wird?
 
Also sollte ich den system class loader benutzen um die Klasse zu laden.

Oder soll ich die klasse 'ModuleMain' vorher mit dem gleichen classloader also dem url class loader laden?
 
Du musst halt dafür sorgen, dass die betreffenden Klassen vom verwendeten ClassLoader bzw. einem seiner direkten/indirekten Vorfahren aufgelöst werden können.
 
Das passiert sowieso. Das Problem taucht z. B. auf, wenn Du die JARs mit zwei URLClassLoader-Instanzen lädst, die voneinander nichts wissen (z. B. nebeneinander):
Code:
    System-CL
        |
        |
   +----+---+
   |        |
 URLCL1    URLCL2
 (jar1)    (jar2)
 Basis <-- Erweiterung
Der URL-ClassLoader 2 (URLCL2) lädt jar2. Dort befindet sich nun eine Klasse, die eine andere Klasse (nämlich aus jar1) benötigt. URLCL2 leitet die Auflösung erst mal an den System-CL weiter. Der findet die Klasse nicht, daher sucht URLCL2 im jar2. Auch dort wird die Klasse nicht gefunden -> Fehler.

Anders würde das hier aussehen:
Code:
    System-CL
       |
       |
     URLCL1
       |
       |
     URLCL2
URLCL2 leitet die Auflösung erst mal an URLCL1 weiter, der wiederum an den System-CL. Der findet nichts, daher sucht URLCL1 in seinem Classpath und findet die Klasse. Alles gut.

Natürlich würde auch das hier gehen:
Code:
    System-CL
       |
       |
     URLCL
   (jar1, jar2)
 
Ok danke es hat geklappt.

Nun habe ich allerdings noch ein anderes problem.
Die Geladene class extended die ModuleMain nun möchte ich zur ModuleMain casten allerdings bekomme ich dann immer einen ClassCastException.


Java:
URLClassLoader moduleLoader = new URLClassLoader(new URL[]{new URL("file:" + path)},
                    APCore.getInstance().getClass().getClassLoader());
            //CHECK MAIN CLASS
            Class clazz = moduleLoader.loadClass(des.getMain());

            Object o = clazz;

            try {

                ModuleMain mainClass = (ModuleMain) o;
               
                isValid = true;
                mainClass.onBeforePluginValidate();
               
                //VALIDATION
                mainClass.onValidate();
               
                //AFTER VALIDATION
                mainClass.afterValidate(true);
            } catch (ClassCastException e) {
                e.printStackTrace();
                isValid = false;
                return;
            }
 

Zurück
Oben