在Java程序中执行另一个jar


114

我编写了几个简单的Java应用程序,分别称为A.jar,B.jar。

现在,我想编写一个GUI Java程序,以便用户可以按按钮A执行A.jar,按按钮B执行B.jar。

我也想在我的GUI程序中输出运行时进程的详细信息。

有什么建议吗?


31
不知道为什么这被否决了。向他解释为什么他的假设可能是错误的,但不要拒绝这个问题。
威廉·布伦德尔

-1基本Java术语使用不正确,问题很模糊,给第二次猜测留下了很多。考虑使用更多详细信息重新表述您的问题,或者先阅读有关Java类路径和其他基础知识的内容。
topchef

21
@grigory:瞧,那是您首先要问的,而不是马上投票。拒绝投票甚至不要求更多信息都没有任何好处……
William Brendel

4
@William,抱歉,比您晚了几秒钟才按下按钮。我保留对以后的评论投反对票的权利。看到问题而没有基本准备和/或不了解或提出问题的努力就令人沮丧。投票对我来说就像是餐馆的小费:根据服务质量,您给与的收益多于或少于标准的12%。因此,我们同意在这里不同意。
topchef

1
@topchef我迟到了11年,但是您说“看到没有基本准备就问到的问题真令人沮丧……”。然后帮助修复它。解释您为什么投票。否则,您根本无法解决问题。
tylerr147

Answers:


63

如果我理解正确,那么看来您想在Java GUI应用程序内部的单独进程中运行jar。

为此,您可以使用:

// 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();

缓冲过程输出始终是一种很好的做法。


21
此解决方案可移植吗?
Pacerier

3
谢谢。我试过使用3个参数(包括“ dir”参数)的exec()函数,但是它不起作用。仅使用一个,我们只需要将3个文件.jar放在同一位置
Duc Tran 2012年

您知道如何获取该RuntimeJava应用程序的对象吗?
stommestack 2014年

我们可以使用ProcessBuilder使用更具移植性的版本吗?
阿南·洛克兹

无法运行程序“ java”:CreateProcess error = 2,系统找不到指定的文件。收到此错误。
君子

27

.jar不可执行。实例化类或调用任何静态方法。

编辑:创建JAR时添加Main-Class条目。

> p.mf(p.mf的内容)

主要类别:pk.Test

>Test.java

package pk;
public class Test{
  public static void main(String []args){
    System.out.println("Hello from Test");
  }
}

使用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));
    }
}

1
我认为这个想法是,只要可以访问jar,您如何将其添加到类路径中以便从中加载类。
Jherico

1
注意:仅在您的PATH中有Java bin时才起作用,默认Windows安装不是这种情况
poussma 2012年

@AVD:应将A.jar文件保存在哪里?
logan 2014年

1
@logan-在要加载程序的目录中。
adatapost 2014年

这种方法会创建一个新的JVM进程还是使用现有的JVM进程?
RahulDeep Attri

17

希望这可以帮助:

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;
}
}

0

如果该jar位于您的类路径中,并且知道它的Main类,则可以只调用main类。以DITA-OT为例:

import org.dita.dost.invoker.CommandLineInvoker;
....
CommandLineInvoker.main('-f', 'html5', '-i', 'samples/sequence.ditamap', '-o', 'test')

请注意,这将使下级jar与您的jar共享内存空间和类路径,并可能引起所有潜在的干扰。如果您不希望这些东西受到污染,则如上所述,您还有其他选择-即:

  • 创建一个带有Jar的新ClassLoader。这样更安全;如果您使用将要使用外来jar的知识来构建事物,则至少可以将新jar的知识隔离到核心类加载器中。这是我们在商店中为插件系统所做的工作;主要应用程序是一个带有ClassLoader工厂的小外壳,API的副本,并且知道真实的应用程序是应为其构建ClassLoader的第一个插件。插件是一对罐子-接口和实现-压缩在一起。所有的ClassLoader共享所有接口,而每个ClassLoader仅了解其自己的实现。堆栈有点复杂,但是它可以通过所有测试并且工作精美。
  • 使用Runtime.getRuntime.exec(...)(完全隔离了jar,但具有正常的“查找应用程序”,“向右转义字符串”,“特定于平台的WTF”和“ OMG系统线程”陷阱等正在运行的系统命令的陷阱。

0

在程序独立运行的情况下,以下操作通过以批处理文件启动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);
    }

在batchfile.bat中,我们可以说:

@echo off
start /min C:\path\to\jarprogram.jar

-3

如果您使用的是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");
        }
    }
}

4
我不认为这个答案OP的问题
斯里兰卡戒Chilakapati
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.