I'm working on a java project that needs a third-party java program running as a server to work.
Normally, I'd do:
java -cp jarfile1.jar:jarfile2.jar className arg1 arg2
And then I'd run my java code. This way it works.
I'd like to know if there is any way to, including the two .jars required into my project, run the class directly from my code instead of having to manually start it.
I've tried to use URLClassLoader
as I saw in some examples, but either I'm doing it wrong or none cover this specific use case.
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new URL("file:///tmp/jarfile1.jar"),new URL("file:///tmp/jarfile2.jar")});
Class<?> cls = classLoader.loadClass("className");
Method method = cls.getDeclaredMethod ("main");
Object instance = cls.newInstance();
Object result = method.invoke (instance);
yields
Exception in thread "main" java.lang.NoClassDefFoundError: alice/tuprolog/lib/InvalidObjectIdException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2615)
at java.lang.Class.getDeclaredMethod(Class.java:2007)
at pkg1.MainClass.main(MainClass.java:54)
Caused by: java.lang.ClassNotFoundException: alice.tuprolog.lib.InvalidObjectIdException
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:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 4 more
Please note that I copied the .jars to /tmp to isolate the failure cause. The files exist and are accessible.
How can I make that run the class as specified above within java code?
Thanks!
I finally fixed it! Things done:
Final working code:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class<?> cls = classLoader.loadClass("className");
Method method = cls.getDeclaredMethod("main", String[].class);
Object instance = cls.newInstance();
Object result = method.invoke(null, (Object)args);
Thanks everyone and specially to VGR and Joop Eggen in the comments for pointing out the error with the second jar!
EDIT: As JB Nizet pointed out in the comments, calling the class's main() method directly is simpler:
className.main(args);
And you're done