Question

I have a class loader that loads the "main" class from all jar files in the /plugins folder this assumes that all jars have the package plugin.(plugin name) containing the class called main. each main class has a constructor called main.

the classes load successfully, but I need to know how to call the main constructor from the loaded class.

(this class/classes are loaded at runtime)

I have tried using this:

Constructor c = cls.getConstructor(Integer.class); //line 41

Plugin plug = (Plugin) c.newInstance(0);

but I get this error:

java.lang.NoSuchMethodException: plugin.myplugin.main.<init>(java.lang.Integer)  
at java.lang.Class.getConstructor0(Unknown Source)  
at java.lang.Class.getConstructor(Unknown Source)  
at hkr.classloader.PluginLoader.loadPlugins(PluginLoader.java:41)  
at hkr.core.startup.InitializeGame.inigame(InitializeGame.java:32)  
at hkr.launcher.main.LauncherMain.main(LauncherMain.java:16)  

package hackers.classloader;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

import org.java.plugin.Plugin;

public class PluginLoader 
{
@SuppressWarnings({ "unused", "rawtypes", "resource" })
    public static void loadPlugins() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        Class cls = null;
        int x = hackers.core.startup.InitializeGame.map.size();
        for (int i = 1; i<=x;i++)
        {
            String className = hackers.core.startup.InitializeGame.map.get(i + "");

            File file  = new File(System.getProperty("user.dir") + File.separator + "plugins" + File.separator + className + ".jar");
            URL url = null;
            try {
                url = file.toURI().toURL();
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }  
            URL[] urls = new URL[]{url};
            ClassLoader cl = new URLClassLoader(urls);

            try {
                cls = cl.loadClass("plugin." + className + ".main");
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Constructor c = cls.getConstructor(Integer.TYPE);
            Plugin plug = (Plugin) c.newInstance(0);
        }
    }
}
Was it helpful?

Solution

If your constructor takes an java.lang.Integer, from what I see, your code should work.

But if your constructor's sole parameter is an int, getConstructor will fail. You have to use Integer.TYPE instead of Integer.class in that case. I I am right, what you need to do is:

Constructor c = cls.getConstructor(Integer.TYPE);

Edit: Based on your edits and your comments, there are several problems.

  1. The class you want to load does not seem to have any explicit constructor, which means that you simply need to do cls.getConstructor()
  2. What you want to execute (public static void main), is a static method for which you normally don't need an instance of a class. Also, I'm not sure "main" would be a good name for the reasons explained by user @Eric B.
  3. Since you want to call a method, You have to instantiate the constructor AND also call the method.

Based on my understanding, the code you would want to execute should be something like that:

Constructor c = cls.getConstructor(); // we get the implicit constructor without parameters
Plugin plugin = (Plugin) c.newInstance(); // we instantiate it, no parameters

Method m = cls.getDeclaredMethod("main", Integer.TYPE);
m.invoke(plugin, 0); // we invoke the method "main" on our dynamically loaded class, with the 0 parameter.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top