可能重複:
Execute another jar in a java program如何從單獨的jar文件運行jar文件?
基本上我想運行從一個現在我工作的一個外部.jar。
I.e.我想從bar.jar運行foo.jar
我試過使用Runtime
和Process
來執行「java -jar foo.jar」,但它會打開foo.jar,然後立即關閉。有小費嗎?
可能重複:
Execute another jar in a java program如何從單獨的jar文件運行jar文件?
基本上我想運行從一個現在我工作的一個外部.jar。
I.e.我想從bar.jar運行foo.jar
我試過使用Runtime
和Process
來執行「java -jar foo.jar」,但它會打開foo.jar,然後立即關閉。有小費嗎?
最簡單的解決方案(as Thorn pointed out)將有罐子作爲構建時依賴,並從你的代碼中靜態調用它:
ExternalJarMainClass.main(new String[]{"arguments", "to", "main"});
但如果這不可行,您可以使用URLClassLoader
來動態加載jar。如果jar確實可以運行,那麼你可以從META-INF/MANIFEST.MF
讀取主類並通過反射調用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"});
檢查java -jar foo.jar
從命令行運行正確。還要確保java在路徑中。在參數中提供到java.exe
的絕對路徑可能會更好。請使用ProcessBuilder
代替Runtime
。
你可以直接運行foo.jar嗎?它有一個主要方法的清單嗎?
我猜你可以。所以你想要啓動一個類的主要方法,如foo.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 您可以在富包加載類在運行時使用類加載器。 見的Javadoc的java.lang.ClassLoader和this example of a CustomClassLoader