NoClassDefFoundError occurs for unknown reason

Discussion in 'Plugin Development' started by Kevinzuman22, Dec 16, 2018.

Thread Status:
Not open for further replies.
  1. I've made a few enum classes, but for some reason a NoClassDefFoundError pops up as soon as one is called. I've searched around the internet, to only find that it might be that the classes in question are not being compiled into the JAR file.

    I've checked if they were included, and they were. I also decompiled the .class file to .java, so check if all the code is still in tact, and it was.

    I can not see where the error should come from, I'm completely clueless.

    The enumerator in question (open)

    Code:
    package me.greenadine.advancedspawners.handler;
    
    import org.bukkit.DyeColor;
    import org.bukkit.Material;
    import org.bukkit.inventory.ItemStack;
    
    import me.greenadine.advancedspawners.Main;
    
    @SuppressWarnings("deprecation")
    public enum ItemHandler {
    
        SPAWNER(new ItemStack(Material.valueOf("MOB_SPAWNER"), 1), new ItemStack(Material.SPAWNER)),
        EXP_BOTTLE(new ItemStack(Material.valueOf("EXP_BOTTLE"), 1), new ItemStack(Material.EXPERIENCE_BOTTLE, 1)),
    
        // Pickaxes
        WOOD_PICKAXE(new ItemStack(Material.valueOf("WOOD_PICKAXE"), 1), new ItemStack(Material.GOLDEN_PICKAXE, 1)),
        GOLD_PICKAXE(new ItemStack(Material.valueOf("GOLD_PICKAXE"), 1), new ItemStack(Material.GOLDEN_PICKAXE, 1)),
    
        // Glass
        WHITE_STAINED_GLASS_PANE(new ItemStack(Material.valueOf("STAINED_GLASS_PANE"), 1, DyeColor.WHITE.getWoolData()), new ItemStack(Material.WHITE_STAINED_GLASS_PANE, 1)),
        LIGHT_BLUE_STAINED_GLASS_PANE(new ItemStack(Material.valueOf("STAINED_GLASS_PANE"), 1, DyeColor.LIGHT_BLUE.getWoolData()), new ItemStack(Material.LIGHT_BLUE_STAINED_GLASS_PANE, 1)),
    
        // Wool
        WHITE_WOOL(new ItemStack(Material.valueOf("WOOL"), 1, DyeColor.WHITE.getWoolData()), new ItemStack(Material.WHITE_WOOL, 1)),
        LIME_WOOL(new ItemStack(Material.valueOf("WOOL"), 1, DyeColor.LIME.getWoolData()), new ItemStack(Material.LIME_WOOL, 1)),
        RED_WOOL(new ItemStack(Material.valueOf("WOOL"), 1, DyeColor.RED.getWoolData()), new ItemStack(Material.RED_WOOL, 1));
    
        ItemStack v1_12;
        ItemStack v1_13;
    
        ItemHandler(ItemStack v1_12, ItemStack v1_13) {
            this.v1_12 = v1_12;
            this.v1_13 = v1_13;
        }
    
        public ItemStack getItem() {
            if(Main.isVersionHigherThan(1, 12)) {
                return v1_13;
            } else {
                return v1_12;
            }
        }
    
        public ItemStack getItem(int amount) {
            return new ItemStack(getType(), amount);
        }
    
        public Material getType() {
            if(Main.isVersionHigherThan(1, 12)) {
                return v1_13.getType();
            } else {
                return v1_12.getType();
            }
        }
    }
    


    How it's being called:
    Code:
    if (b.getType() != ItemHandler.SPAWNER.getType()) {
                return;
            }
    This snippet of code is being used during a PlayerInteractEvent.

    The error log:
    https://pastebin.com/M5E6JXKP

    Could it be that using static access causes the issue, by using 'DyeColor.RED.getWoolData()'?
     
  2. @Kevinzuman22

    I think I see what goes wrong, it's about the line:
    SPAWNER(new ItemStack(Material.valueOf("MOB_SPAWNER"), 1), new ItemStack(Material.SPAWNER)),

    You should probably use new ItemStack(Material.valueOf("SPAWNER")) instead of new ItemStack(Material.SPAWNER).

    The error occurs becacuse Material.SPAWNER doesn't exist in the bukkit version that is being used on the server (even though the itemstack you are creating is not used, trying to create it still causes an error). The same holds for all other enum constants in ItemHandler. You should always use Material.valueOf() if you need materials with different names in different bukkit versions.
     
  3. @knokko it seems that the problem is indeed in that it's trying to create an ItemStack with a non-existing Material type. But, unfortunately, using Material.valueOf("SPAWNER") does not work. It will still give me 'java.lang.IllegalArgumentException: No enum constant org.bukkit.Material.SPAWNER', followed by a NoClassDefFoundError.

    The only way around this is, I would assume, finding a way of only creating the item if the version it's for is being used, and having the other version just be ignored. Could I create 2 seperate classes for each version, and do something with that?
     
  4. @Kevinzuman22

    Indeed, that causes an IllegalArgumentException. I was hoping Material.valueOf would return null...

    Allright, I know something that should work:
    Instead of an ItemHandler constructor that requires 2 ItemStack's, use an ItemHandler constructor that requires 2 strings.
    And instead of storing both the 1.12 and the 1.13 itemstack in every ItemHandler, only store the one that you need.
    Use the constructor like this:
    Code:
    ItemHandler(String materialName12, String materialName13){
    if (
    Main.isVersionHigherThan(1, 12)
    ){
    this.itemstack = new ItemStack(Material.valueOf(materialName13));
    } else {
    this.itemstack = new ItemStack(Material.valueOf(materialName12));
    }
    }
     
Thread Status:
Not open for further replies.

Share This Page