Search code examples
javaclassloaderbukkit

Class loader returns a NoSuchMethodException error


I've been Trying to load some classes on demand so that I can run their execute methods as it is more optimized but it returns a NoSuchMethodFound error

Class trying to load Commandtest

Object execute = Class.forName("com.kkosyfarinis.spigot.xssentials.test." + _className);
Class<?>[] paramTypes = {Server.class, CommandSender.class, String.class, String[].class};
executeCommand = execute.getClass().getMethod("execute", int.class);
//
//For the server, commandsender(...)
//executeCommand.invoke(server, sender, label, args);
//
//for int
//executeCommand.invoke(5);
//
//for empty
//executeCommand.invoke();

Commandtest.java

package com.kkosyfarinis.spigot.xssentials.test;

import org.bukkit.Server;
import org.bukkit.command.CommandSender;

public class Commandtest extends CommandHandlerTest{

    protected Commandtest() {
        super("test");
    }

    public void execute(Server server, CommandSender sender, String label, String args)
    {
        System.out.println("this is a test");
    }

    protected void execute(int test)
    {
        System.out.println(test);
    }

    protected void execute()
    {
        System.out.println("this is a test");
    }

}

And it returns this

[18:13:00 WARN]: java.lang.NoSuchMethodException: java.lang.Class.execute(int) [18:13:00 WARN]: at java.lang.Class.getMethod(Unknown Source) [18:13:00 WARN]: at com.kkosyfarinis.spigot.xssentials.test.CommandHandlerTest.execute(CommandHandlerTest.java:53) [18:13:00 WARN]: at com.kkosyfarinis.spigot.xssentials.Xssentials.onCommand(Xssentials.java:137) [18:13:00 WARN]: at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) [18:13:00 WARN]: at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) [18:13:00 WARN]: at org.bukkit.craftbukkit.v1_11_R1.CraftServer.dispatchCommand(CraftServer.java:650) [18:13:00 WARN]: at org.bukkit.craftbukkit.v1_11_R1.CraftServer.dispatchServerCommand(CraftServer.java:636) [18:13:00 WARN]: at net.minecraft.server.v1_11_R1.DedicatedServer.aM(DedicatedServer.java:437) [18:13:00 WARN]: at net.minecraft.server.v1_11_R1.DedicatedServer.D(DedicatedServer.java:400) [18:13:00 WARN]: at net.minecraft.server.v1_11_R1.MinecraftServer.C(MinecraftServer.java:678) [18:13:00 WARN]: at net.minecraft.server.v1_11_R1.MinecraftServer.run(MinecraftServer.java:576) [18:13:00 WARN]: at java.lang.Thread.run(Unknown Source)

I did try using as the paramTypes: -empty- for the no argument method, int.class for the integer argument one, and the Server, CommandSender(...) but non of those worked at all

Any ideas on how to fix this?


Solution

  • You are trying to get a method named execute on a Class Object.

    Why?

    This happens because when you call Class.forName it returns a Class instance for the object com.kkosyfarinis.spigot.xssentials.test.*. After that you call getClass on the previous class instance, this returns a Class instance for the object Class, after what you try to get an non existing method.

    To solve this you need to remove the superfluous call to getClass so it works correctly.

    Class<?> execute = Class.forName("com.kkosyfarinis.spigot.xssentials.test." + _className);
    // Class<?>[] paramTypes = {Server.class, CommandSender.class, String.class, String[].class};
    executeCommand = execute.getMethod("execute", int.class);
    

    Then you also need to call invoke to finally call the method. care should be taken here, because your method is not static, this means you also need to pass an instance of the class you want to execute the method on.

    This is really easy, because Class also has a useful newInstance method that you can use to make a new instance.

    This can be used like this:

    Object instance = clazz.newInstance();
    executeCommand.invoke(instance, new Object[]{2147483647});