如何从单独的jar文件运行jar文件?

可能重复:
在java程序中执行另一个jar

基本上我想从我正在处理的那个上运行一个外部.jar。

即我想从bar.jar运行foo.jar

我已经尝试使用RuntimeProcess来执行“java -jar foo.jar”,但它会打开foo.jar然后立即关闭。 有小费吗?

最简单的解决方案( 如Thorn指出的那样 )是将jar作为构建时依赖项并从代码中静态调用它:

 ExternalJarMainClass.main(new String[]{"arguments", "to", "main"}); 

但如果不可能,您可以使用URLClassLoader动态加载jar。 如果jar确实可以运行,那么你可以从META-INF/MANIFEST.MF读取主类并通过reflection调用main

这是创建单独进程的另一种方法,因为外部代码将在与应用程序相同的进程中运行。 也许这是可取的,也许不是 – 这取决于具体情况。

下面是一个(草率编写和有缺陷的)示例助手类,它就是这样做的。

 import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.regex.Matcher; import java.util.regex.Pattern; public class JarRunner { private final Method entryPoint; public JarRunner(File jarFile) throws ClassNotFoundException, IOException, NoSuchMethodException { URL jarUrl = jarFile.toURI().toURL(); URLClassLoader loader = URLClassLoader.newInstance( new URL[]{jarUrl}); URL manifestUrl = loader.findResource("META-INF/MANIFEST.MF"); String manifest = resourceToString(manifestUrl); Class clazz = loader.loadClass(findMainClassName(manifest)); entryPoint = clazz.getMethod("main", String[].class); } public void run(String[] argsToMain) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { entryPoint.invoke(null, (Object) argsToMain); } private static String resourceToString(URL url) throws IOException { InputStream contentStream = url.openStream(); try { BufferedReader r = new BufferedReader( new InputStreamReader(contentStream)); StringBuilder sb = new StringBuilder(); String line = null; do { line = r.readLine(); if (line != null) { sb.append(line).append('\n'); } } while (line != null); return sb.toString(); } finally { contentStream.close(); } } private static String findMainClassName(String manifest) { Matcher m = MAIN_CLASS_PATTERN.matcher(manifest); if (m.find()) { return m.group(1); } return null; } private static final Pattern MAIN_CLASS_PATTERN = Pattern.compile("Main-Class: (.+)"); } 

样品用法:

 JarRunner jr = new JarRunner(new File("path/to/MyJar.jar")); jr.run(new String[]{"arg1", "arg2"}); 

你能直接运行foo.jar吗? 它是否有主要方法的清单?

我猜你可以。 所以你想在像foo.Main这样的类中启动main方法

选项1:在类路径中包含foo.jar。 如果您使用的是IDE,那么这只是将foo.jar添加为库。 现在您可以自由地导入包(让我们调用包foo)并从一行Java代码启动第二个java程序:foo.Main.main(null); 您很可能希望在单独的线程中执行此操作:

 class FooRunner extends Thread { public void run() { foo.Main.main(null); } } 

然后你会用这个启动:

 FooRunner secondaryApp = new FooRunner(); secondaryApp.start(); 

选项2您可以使用类加载器在运行时加载Foo包中的类。 请参阅Javadocs以获取java.lang.ClassLoader和CustomClassLoader的此示例

检查java -jar foo.jar是否从命令行正确运行。 还要确保路径中有java。 在参数中提供java.exe绝对路径可能更好。

请考虑使用ProcessBuilder而不是Runtime