可能性の重複:
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
に与えるほうが良いでしょう。
Runtime
の代わりにProcessBuilder
を使用してください。
foo.jarを直接実行できますか?それは主な方法を持つマニフェストを持っていますか?
私はあなたができると推測しています。したがって、foo.Mainのようなクラスの中でmainメソッドを起動したいとします。
オプション1:クラスパスにfoo.jarを含めます。 IDEを使用している場合は、foo.jarをライブラリとして追加するだけです。今すぐパッケージをインポートして(パッケージfooを呼び出せるように)、Javaコードの1行から2番目のJavaプログラムを起動することができます。 foo.Main.main(null); ほとんどの場合、あなたが別のスレッドでこれをしたいと思う:
class FooRunner extends Thread {
public void run() {
foo.Main.main(null);
}
}
、その後、あなたはこれで起動します:
FooRunner secondaryApp = new FooRunner();
secondaryApp.start();
オプション2 あなたはfooパッケージ内のクラスをロードすることができます実行時にクラスローダーを使用して たjava.lang.ClassLoaderのJavadocを参照してくださいthis example of a CustomClassLoader