ClassNotFound for jar within project?

Discussion in 'Plugin Development' started by Malikk, Jun 20, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    Malikk

    Hey everybody,

    I'm having an issue hooking in the API of another plugin. It has custom exceptions, so in order to keep this as a soft depend, I've included the plugin I'm hooking within my own jar.

    I've set the build path correctly and double checked my classpath, and everything seems to be correct. Everything compiles correctly, as well, but the plugin won't load up due to a ClassNotFoundException.

    How is this possible? The jar is directly included in my project and I've double checked that I am, in fact, exporting the folder its in as well.

    I am really stumped here.

    Thanks in advance.
     
  2. Ehh you don't need to do that... just use:
    Code:
    if(Bukkit.getPluginManager().getPlugin("YourHookedPlugin") instanceof YourHookedPluginMainClass)
    {
        // plugin exists, use it.
    }
    If that's not it... you should show some code and the stacktrace itself, which usually clears stuff up.
     
  3. Offline

    Malikk

    I understand getting the running instance of a plugin, that's not the issue. The issue is the custom exceptions. They throw ClassNotFoundExceptions when the class they are in is instantiated.

    Code:
    try {
                allowed = api.getFlagValue(player, "EpicGlass", sregion);
            } catch (FlagNotFoundException e) {
                plugin.log("FlagNotFound");
            } catch (InvalidFlagException e) {
                plugin.log("InvalidFlag");
            } catch (InvalidRegionException e) {
                plugin.log("Invalid Region");
            }
    
    These exception classes are all referenced and the build path is set from a jar which is included in my own jar, yet they still throw ClassNotFoundExceptions.

    I don't think it's going to tell you anything at all, but here's the error.

    Show Spoiler

    01:21:36 [SEVERE] Could not load 'plugins/EpicGlass.jar' in folder 'plugins'
    org.bukkit.plugin.InvalidPluginException: java.lang.NoClassDefFoundError: us/twoguys/shield/exceptions/FlagNotFoundException
    at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:149)
    at org.bukkit.plugin.SimplePluginManager.loadPlugin(SimplePluginManager.java:305)
    at org.bukkit.plugin.SimplePluginManager.loadPlugins(SimplePluginManager.java:230)
    at org.bukkit.craftbukkit.CraftServer.loadPlugins(CraftServer.java:213)
    at org.bukkit.craftbukkit.CraftServer.reload(CraftServer.java:550)
    at org.bukkit.Bukkit.reload(Bukkit.java:182)
    at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:22)
    at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:166)
    at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:479)
    at org.bukkit.craftbukkit.CraftServer.dispatchServerCommand(CraftServer.java:475)
    at net.minecraft.server.MinecraftServer.b(MinecraftServer.java:612)
    at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:581)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:459)
    at net.minecraft.server.ThreadServerApplication.run(SourceFile:492)
    Caused by: java.lang.NoClassDefFoundError: us/twoguys/shield/exceptions/FlagNotFoundException
    at me.jordan.epicGlass.EpicGlass.<init>(EpicGlass.java:30)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:145)
    ... 13 more
    Caused by: java.lang.ClassNotFoundException: us.twoguys.shield.exceptions.FlagNotFoundException
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:41)
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:29)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:315)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:250)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:398)
    ... 19 more
     
  4. Offline

    Njol

    Please remove everything that is not your code from your jar, this will just cause issues.
    Try to move everything that depends on the other plugin into onEnable(). Some of Bukkit's methods are not available when the plugin is instantiated.
     
  5. Offline

    Malikk

    The issue is that if the server doesn't have the hooked plugin, these classes can't be found and throw errors, so I'm attempting to add the jar to my jar so that even if the plugin isn't found, I can still load the classes without any issues.

    I realize that I could essentially quarantine these exceptions in their own class, but I really don't want to do that. It's very clean the way it is, and I'm simply trying to figure out how to load those classes from an included jar. I can't figure out why it doesn't work during runtime, because everything compiles correctly and the build path is correct as well.

    This has nothing to do with Bukkit at all. This has to do with class references that can't be found upon class instantiation.
     
  6. Offline

    Njol

    Maybe in order for your plugin to catch those exceptions their classes have to be loaded, but as long as the other plugin doesn't throw one they are not loaded. In this case you can try to load them with Class.forName("...") or ask the other plugin's author to load the exception classes when his plugin is instantiated.
     
  7. Offline

    Malikk

    There's no issue when the server has both plugins, only when it doesn't have the hooked one.
     
  8. Offline

    desht

    The only way around this is to isolate all references to those exceptions into their own class(es) in your plugin, and only instantiate (or call static methods of) those classes if you know you've successfully hooked the plugin.

    I do something similar with WorldEdit in my ChessCraft plugin: see https://github.com/desht/ChessCraft...me/desht/chesscraft/blocks/TerrainBackup.java. Note that the WorldEdit API can throw a com.sk89q.worldedit.data.DataException and code in my TerrainBackup class catches that. As long as I ensure that all TerrainBackup methods are only called when WorldEdit is loaded, there's no problem. E.g. see https://github.com/desht/ChessCraft...java/me/desht/chesscraft/chess/BoardView.java line 467.
     
  9. Offline

    Njol

    So Java tries to load the exception's classes even though their catch clause is never reached?
    In this case I can think of 2 solutions: Either put everything that handles the custom exceptions into a class you're sure you never load if the other plugin is not enabled, or catch a generic Exception and then use instanceof to find what kind of exception was caught.

    edit: ninja'ed
     
  10. Offline

    desht

    Yeah, seems that way. The JVM will need the exception class(es) loaded to be able to match against them, regardless of whether or not the catch clause is actually hit.
     
  11. Offline

    Malikk

    I realize that I could easily just isolate everything, but why can't I just add the jar I'm referencing to my own? I can't figure out why it can't find those exception classes at runtime, even tho they are in my own project.

    bump.

    I'm sure this is a simple problem. All I'm trying to do is reference a class from a jar in my project, but it's not finding the classes at runtime.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 26, 2016
  12. Offline

    Njol

    I guess the jar inside your jar is not in your classpath
     
  13. Offline

    Malikk

    The classpath is correct
     
  14. Offline

    Njol

    Do you mean the .classpath generated by Eclipse (or aother GUI?) is correct? This file is only used by Eclipse and ignored by the JVM.
    It's the runtime classpath that's important which can be e.g. set in the command line with -cp, though I don't think it's possible to specify a jar inside a jar. You'll have to load the jar yourself, but this is less desirable that simply moving all code that catches the custom exceptions in a separate class.
     
    Malikk likes this.
  15. yo u cant load classes from a jar inside a jar
     
  16. Offline

    Malikk

    I guess I'm just not understanding why this isn't possible.

    But thanks for the input, everyone.

    I'm going to go ahead and just isolate the references, but for future reference, is it possible for to copy classes from a jar and load them myself? without rewriting or copying, etc.

    Like, in this case, would it be possible to just pull out those exception classes so that I can use them?

    Sorry if this is a dumb question, it's not something I have a lot of experience with.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 26, 2016
  17. Offline

    Sagacious_Zed Bukkit Docs

    Yes, it is possible to shade the contents of a jar, the easiest way i find is to do it with maven, however this itself will cause problems if you intend for another plugin to exist most of the time.
     
Thread Status:
Not open for further replies.

Share This Page