I am making a program that operates as multiple JAR file dependencies. Basically, the thing loops through the .class files in a JAR file and gets a Class object for each of them. Each JAR has a Plugin.class file that I don't want to be available, but I want all the Classes to be accessible by other JAR dependencies as well as the main program. For example, in one JAR I have the class something.somethingelse.SomeClass, and from a second one (I made sure it is loaded second) I want to be able to import (at execution because it's in a separate JARfile) something.somethingelse.SomeClass and use it. I Have tried this after loading it into a Class object but it gives me ClassNotFound
errors. I am using the newest java update and the newest version of eclipse IDE. I have three projects, "main", "aaa", and "aab". I have aaa and aab exported to JARs of which the contents are loaded into Class objects by main. aaa is loaded before aab, and I want aab to be able to access the classes from aaa through import aaa.Class
. How can I (from main) make the classes of both jarfiles available to each other?
Here is my load plugin function:
public static void load(File file) throws Exception
{
JarFile jarFile = new JarFile(file);
Enumeration e = jarFile.entries();
URL[] urls = new URL[] { file.toURI().toURL() };
ClassLoader cl = new URLClassLoader(urls);
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
if(je.isDirectory() || !je.getName().endsWith(".class") || je.getName() == "Plugin.class"){
continue;
}
// -6 because of .class
String className = je.getName().substring(0,je.getName().length()-6);
className = className.replace('/', '.');
Class c = cl.loadClass(className);
}
ClassLoader loader = new URLClassLoader(urls);
Class c = loader.loadClass("Plugin");
Object cobj = c.newInstance();
Method[] allMethods = c.getDeclaredMethods();
Method method = null;
boolean found = false;
for (Method m : allMethods) {
String mname = m.getName();
if (mname == "startPlugin"){
method = m;
found = true;
}
}
if(found)
{
method.invoke(cobj);
}
else
{
//skip class
}
}
And then my first JAR (aaa.jar) declares a class called hlfl.ui.UserInterface. My second JAR's Plugin class is as follows:
import hlfl.ui.*;
public class Plugin {
//THIS DEPENDENCY EXPORTS TO: aab.jar
public void startPlugin()
{
System.out.println("Plugin Loading Interface Loaded [AAB]");
UserInterface c = new UserInterface();
}
}
But when I run it it gives me the following:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun. reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sf.htmlguy.hlaunch.PluginLoader.load(PluginLoader.java:58)
at sf.htmlguy.hlaunch.PluginLoader.loadAll(PluginLoader.java:22)
at sf.htmlguy.hlaunch.HLaunch.main(HLaunch.java:14)
Caused by: java.lang.NoClassDefFoundError: hlfl/ui/UserInterface
at Plugin.startPlugin(Plugin.java:7)
... 7 more
Caused by: java.lang.ClassNotFoundException: hlfl.ui.UserInterface
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 8 more
Just in case, the code is on SourceForge (the three projects are in subdirectories, "hlaunch for linux" is the main one.): https://sourceforge.net/p/hlaunch/code