2

//UPDATE//

Now I can load a Jar, but how can I run methods from it?

Cardinal System
  • 2,749
  • 3
  • 21
  • 42
sentostv
  • 21
  • 1
  • 4

3 Answers3

1

From the main JAR file where you need to plug games.jar:

  • First get the URL for your games.jar file (use File.toURI().toURL()) and put it in an array (let's call the array urlArray).
  • Next get a URLClassLoader instance to load games.jar:

    URLClassLoader urlClassLoader = URLClassLoader.newInstance(urlArray);
    
  • Now you can instantiate any class from the games.jar with the Class.forName if you pass the new class loader you just created as third parameter:

    Class<? extends Main> mainClass = (Class<? extends Main>)
    Class.forName("Main", true, urlClassLoader);
    
  • On mainClass you can now call your method: mainClass.loaded();

x80486
  • 6,627
  • 5
  • 52
  • 111
Olivier Meurice
  • 554
  • 8
  • 17
1

There are two parts to this. First, you need to import the jar. This can be done at runtime using a slight hack with reflection:

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public void importJar(File file) {
    Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    addURL.setAccessible(True);
    addURL.invoke(URLClassLoader.getSystemClassLoader(), new Object[] {file.toURI().toURL()});
}    

Now you can import a jar at runtime. If you simply have the path to the jar, you can easily convert it to a File:

importJar(new File("path/to/jar"));

Second, you need to find the classes defined in your jar. There does not appear to be a built-in way to do this, so you'll have to manually examine the jar itself for classes.

import java.lang.Class;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarFile;
import java.util.jar.JarEntry;
public List<Class<?>> findJarClasses(File file) {
    ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
    JarFile jar = new JarFile(file);
    Enumeration<JarEntry> entries = jar.entries();
    while (entries.hasMoreElements()) {
        JarEntry entry = entries.nextElement();
        String name = entry.getName();
        if (name.endsWith(".class")) {
            name = name.substring(0, name.lastIndexOf('.'));
            Class<?> cls = Class.forName(name);
            classes.add(cls);
        }
    }
    return classes;
}

Finally, you can iterate over the classes to determine if any of them implement your desired interface.

File jarFile = new File("path/to/Games.jar");
importJar(jarFile);
List<Class<?>> classes = findJarClasses(jarFile);
for (Class<?> cls : classes) {
    if (cls.isInstance(YourInterface.class)) {
        // Instantiate class.
        YearInterface obj = (YourInterface)cls.newInstance();
        // Call `loaded()` method.
        obj.loaded();
    }
}
Community
  • 1
  • 1
Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
  • And how can i run a method in this Class? – sentostv Nov 22 '14 at 17:33
  • You can instantiate the class using either `cls.newInstance()` or `cls.getConstructor(ArgumentClasses...).newInstance(arguments)` if the constructor has arguments. See also my update. – Uyghur Lives Matter Nov 22 '14 at 17:55
  • I always get an Error [11:35:29 ERROR]: Error occurred while enabling Arcade v0.1 (Is it up to date?) java.lang.NoClassDefFoundError: arcade/interfaces/game – sentostv Nov 23 '14 at 10:36
  • @sentostv I'm unfamiliar that error. Perhaps you could add all of your jars to the classpath, and omit the `importJar()` call. – Uyghur Lives Matter Nov 24 '14 at 13:37
  • Ok so can U helpme ? I have one Jar with the Loader and in the second jar I have a Method which i want to run from the first, what I have to do ? – sentostv Nov 26 '14 at 18:32
  • @sentostv Update your question with where you are stuck. Include any classes and which jars they belong to that may be relevant. – Uyghur Lives Matter Nov 26 '14 at 22:07
0
  1. Create a classloader with the jar's file url.
  2. Ask the classloader to load the game's main class by name
  3. Create a new instance of the game's main class
  4. Cast it to some 'Game' interface your plugin loader knows
  5. Invoke the methods on the interface to start the game.
GeertPt
  • 16,398
  • 2
  • 37
  • 61