在 Java 程序中执行另一个 jar
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1320476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Execute another jar in a Java program
提问by winsontan520
I had written several simple java applications named as A.jar, B.jar.
我写了几个简单的java应用程序,分别命名为A.jar、B.jar。
Now i want to write a GUI java program so that user can press button A to execute A.jar and button B to execute B.jar.
现在我想编写一个 GUI java 程序,以便用户可以按下按钮 A 执行 A.jar 和按钮 B 执行 B.jar。
Also i want to output the run-time process detail in my GUI program.
我还想在我的 GUI 程序中输出运行时进程的详细信息。
Any suggestion?
有什么建议吗?
回答by adatapost
.jar isn't executable. Instantiate classes or make call to any static method.
.jar 不可执行。实例化类或调用任何静态方法。
EDIT: Add Main-Class entry while creating a JAR.
编辑:在创建 JAR 时添加主类条目。
>p.mf (content of p.mf)
>p.mf(p.mf 的内容)
Main-Class: pk.Test
主类:pk.Test
>Test.java
package pk;
public class Test{
public static void main(String []args){
System.out.println("Hello from Test");
}
}
Use Process class and it's methods,
使用 Process 类及其方法,
public class Exec
{
public static void main(String []args) throws Exception
{
Process ps=Runtime.getRuntime().exec(new String[]{"java","-jar","A.jar"});
ps.waitFor();
java.io.InputStream is=ps.getInputStream();
byte b[]=new byte[is.available()];
is.read(b,0,b.length);
System.out.println(new String(b));
}
}
回答by gjrwebber
If I understand correctly it appears you want to run the jars in a separate process from inside your java GUI application.
如果我理解正确,您似乎希望在 Java GUI 应用程序内部的单独进程中运行 jar。
To do this you can use:
为此,您可以使用:
// Run a java app in a separate system process
Process proc = Runtime.getRuntime().exec("java -jar A.jar");
// Then retreive the process output
InputStream in = proc.getInputStream();
InputStream err = proc.getErrorStream();
Its always good practice to buffer the output of the process.
缓冲过程的输出总是好的做法。
回答by rupa
If you are java 1.6 then the following can also be done:
如果您是 java 1.6,则还可以执行以下操作:
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class CompilerExample {
public static void main(String[] args) {
String fileToCompile = "/Users/rupas/VolatileExample.java";
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int compilationResult = compiler.run(null, null, null, fileToCompile);
if (compilationResult == 0) {
System.out.println("Compilation is successful");
} else {
System.out.println("Compilation Failed");
}
}
}
回答by Fordi
If the jar's in your classpath, and you know its Main class, you can just invoke the main class. Using DITA-OT as an example:
如果 jar 在您的类路径中,并且您知道它的 Main 类,则可以调用主类。以 DITA-OT 为例:
import org.dita.dost.invoker.CommandLineInvoker;
....
CommandLineInvoker.main('-f', 'html5', '-i', 'samples/sequence.ditamap', '-o', 'test')
Note this will make the subordinate jar share memory space and a classpath with your jar, with all the potential for interference that can cause. If you don't want that stuff polluted, you have other options, as mentioned above - namely:
请注意,这将使从属 jar 与您的 jar 共享内存空间和类路径,并可能导致干扰。如果您不希望这些东西受到污染,您还有其他选择,如上所述 - 即:
- create a new ClassLoader with the jar in it. This is more safe; you can at least isolate the new jar's knowledge to a core classloader if you architect things with the knowledge that you'll be making use of alien jars. It's what we do in my shop for our plugins system; the main application is a tiny shell with a ClassLoader factory, a copy of the API, and knowledge that the real application is the first plugin for which it should build a ClassLoader. Plugins are a pair of jars - interface and implementation - that are zipped up together. The ClassLoaders all share all the interfaces, while each ClassLoader only has knowledge of its own implementation. The stack's a little complex, but it passes all tests and works beautifully.
- use
Runtime.getRuntime.exec(...)
(which wholly isolates the jar, but has the normal "find the application", "escape your strings right", "platform-specific WTF", and "OMG System Threads" pitfalls of running system commands.
- 创建一个包含 jar 的新 ClassLoader。这样更安全;如果您根据将使用外来 jar 的知识构建事物,则至少可以将新 jar 的知识隔离到核心类加载器。这就是我们在我的商店中为我们的插件系统所做的;主应用程序是一个带有 ClassLoader 工厂的小外壳、API 的副本,并且知道真正的应用程序是第一个应该为其构建 ClassLoader 的插件。插件是一对 jars - 接口和实现 - 被压缩在一起。ClassLoader 都共享所有的接口,而每个 ClassLoader 只知道自己的实现。堆栈有点复杂,但它通过了所有测试并且运行良好。
- 使用
Runtime.getRuntime.exec(...)
(它完全隔离了 jar,但具有正常的“查找应用程序”、“正确转义字符串”、“特定于平台的 WTF”和“OMG 系统线程”运行系统命令的陷阱。
回答by Swarvanu Sengupta
Hope this helps:
希望这可以帮助:
public class JarExecutor {
private BufferedReader error;
private BufferedReader op;
private int exitVal;
public void executeJar(String jarFilePath, List<String> args) throws JarExecutorException {
// Create run arguments for the
final List<String> actualArgs = new ArrayList<String>();
actualArgs.add(0, "java");
actualArgs.add(1, "-jar");
actualArgs.add(2, jarFilePath);
actualArgs.addAll(args);
try {
final Runtime re = Runtime.getRuntime();
//final Process command = re.exec(cmdString, args.toArray(new String[0]));
final Process command = re.exec(actualArgs.toArray(new String[0]));
this.error = new BufferedReader(new InputStreamReader(command.getErrorStream()));
this.op = new BufferedReader(new InputStreamReader(command.getInputStream()));
// Wait for the application to Finish
command.waitFor();
this.exitVal = command.exitValue();
if (this.exitVal != 0) {
throw new IOException("Failed to execure jar, " + this.getExecutionLog());
}
} catch (final IOException | InterruptedException e) {
throw new JarExecutorException(e);
}
}
public String getExecutionLog() {
String error = "";
String line;
try {
while((line = this.error.readLine()) != null) {
error = error + "\n" + line;
}
} catch (final IOException e) {
}
String output = "";
try {
while((line = this.op.readLine()) != null) {
output = output + "\n" + line;
}
} catch (final IOException e) {
}
try {
this.error.close();
this.op.close();
} catch (final IOException e) {
}
return "exitVal: " + this.exitVal + ", error: " + error + ", output: " + output;
}
}
回答by Dawood Morris
The following works by starting the jar with a batch file, in case the program runs as a stand alone:
以下通过使用批处理文件启动 jar 来工作,以防程序作为独立运行:
public static void startExtJarProgram(){
String extJar = Paths.get("C:\absolute\path\to\batchfile.bat").toString();
ProcessBuilder processBuilder = new ProcessBuilder(extJar);
processBuilder.redirectError(new File(Paths.get("C:\path\to\JavaProcessOutput\extJar_out_put.txt").toString()));
processBuilder.redirectInput();
try {
final Process process = processBuilder.start();
try {
final int exitStatus = process.waitFor();
if(exitStatus==0){
System.out.println("External Jar Started Successfully.");
System.exit(0); //or whatever suits
}else{
System.out.println("There was an error starting external Jar. Perhaps path issues. Use exit code "+exitStatus+" for details.");
System.out.println("Check also C:\path\to\JavaProcessOutput\extJar_out_put.txt file for additional details.");
System.exit(1);//whatever
}
} catch (InterruptedException ex) {
System.out.println("InterruptedException: "+ex.getMessage());
}
} catch (IOException ex) {
System.out.println("IOException. Faild to start process. Reason: "+ex.getMessage());
}
System.out.println("Process Terminated.");
System.exit(0);
}
In the batchfile.bat then we can say:
在 batchfile.bat 中,我们可以说:
@echo off
start /min C:\path\to\jarprogram.jar