简体   繁体   English

无法从Java启动程序(使用ProcessBuilder)

[英]Failure to start program from java (using ProcessBuilder)

I am trying to call cleartool from an java application, but cleartool hangs even for a simple "-version" argument. 我正在尝试从Java应用程序调用cleartool,但是即使对于简单的“ -version”参数,cleartool也会挂起。 Running cleardiff instead of cleartool works fine, so apparently there is something specific with the cleartool program (which I assume is related to its interactive capabilities). 运行cleardiff而不是cleartool可以正常工作,因此显然cleartool程序有一些特定的东西(我认为这与其交互功能有关)。

The following program 以下程序

import java.io.*;
import java.util.*;

public class ExecTesting extends Thread {

    private List<String> command = new ArrayList<String>();

    public ExecTesting (List<String> command) {
        super();
        this.command = command;
    }

    private void print(String s) {
        System.out.println(s);
    }

    @Override
    public void run() {
        Process process;
        OutputStream stdin;
        InputStream stdout;
        InputStream stderr;
        String line;

        try {
            String commandString = joinList(command, " ");
            print("Executing: " + commandString);

            // runtime.exec has several issues (http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1)
            // better to use ProcessBuilder (http://java.sun.com/developer/JDCTechTips/2005/tt0727.html#2)
            //process = Runtime.getRuntime().exec(commandString);
            process = new ProcessBuilder(command).start();
            // it fails in both cases though

            stdin  = process.getOutputStream();
            stdout = process.getInputStream();
            stderr = process.getErrorStream();

            BufferedReader bufferedStderr = new BufferedReader(new InputStreamReader(stderr));
            while ((line = bufferedStderr.readLine()) != null) {
                print("stderr: " + line);
            }
            bufferedStderr.close();

            BufferedReader bufferedStdout = new BufferedReader(new InputStreamReader(stdout));
            while ((line = bufferedStdout.readLine()) != null) {
                print("stdout: " + line);
            }
            bufferedStdout.close();

            stdin.close();
            stdout.close();
            stderr.close();

            process.waitFor();
            print("Execution finished, exit code " + process.exitValue());
            process.destroy();
        } catch (IOException e) {
            print("IOException: " +e.getStackTrace());
        } catch (InterruptedException e) {
            print("InterruptedException: " + e.getStackTrace());
        }

    }

    /* assumes a list with at least one element */
    private static String joinList(List<String> list, String glue) {
        Iterator<String> i = list.iterator();
        String ret = i.next();
        while (i.hasNext()) {
            ret += glue + i.next();
        }
        return ret;
    }

    public static void main(String[] args) {
        ArrayList<String> cmd1 = new ArrayList<String>();
        cmd1.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleardiff.exe");
        cmd1.add("-version");
        ExecTesting et1 = new ExecTesting(cmd1);
        et1.start();

        ArrayList<String> cmd2 = new ArrayList<String>();
        //cmd2.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleardiff.exe");
        cmd2.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleartool.exe");
        cmd2.add("-version");
        ExecTesting et2 = new ExecTesting(cmd2);
        et2.start();

        et1 = new ExecTesting(cmd1);
        et1.start();
    }
}

gives the following output 提供以下输出

Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleartool.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
stdout: cleardiff                         2003.06.10+ (Tue Jul 13 14:02:05  2004)
Execution finished, exit code 0

hanging on the execution of the cleartool command. 挂在执行cleartool命令上。 If instead cmd2 is changed to cleardiff the output is as expected 如果改为将cmd2更改为cleardiff,则输出与预期的一样

Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
stdout: cleardiff                         2003.06.10+ (Tue Jul 13 14:02:05  2004)
Execution finished, exit code 0
stdout: cleardiff                         2003.06.10+ (Tue Jul 13 14:02:05  2004)
Execution finished, exit code 0
stdout: cleardiff                         2003.06.10+ (Tue Jul 13 14:02:05  2004)
Execution finished, exit code 0

Question: Does anyone know why cleartool is hanging and how to fix? 问题:有谁知道为什么cleartool挂起以及如何修复?

It seems you close the I/O streams BEFORE you start to wait for the termination. 似乎开始等待终止之前关闭了I / O流。 Also you read the stderr and stdout sequentially. 您也可以顺序阅读stderr和stdout。 However, the read to stderr blocks as there are no errors printed by the application and you don't move to the phase where you read the stdout. 但是,读取到stderr会阻塞,因为应用程序不会打印任何错误,并且您不会进入读取stdout的阶段。 This deadlocks. 陷入僵局。

You could join the stderr and stdout via ProcessBuilder.redirectErrorStream() and then you need only to read stdout. 您可以通过ProcessBuilder.redirectErrorStream()加入stderr和stdout,然后只需要读取stdout。

Your sample works in some cases because when you are blocked on the stderr, the application response on the stdout doesn't hit the size of the communication buffer. 您的示例在某些情况下可行,因为当您在stderr上被阻止时,stdout上的应用程序响应不会达到通信缓冲区的大小。 When the application quits, the stderr loop exits and the loop for stdout is able to retieve the contents of that buffer. 当应用程序退出时,stderr循环退出,并且stdout的循环能够重新分配该缓冲区的内容。

You should consume the stdout and stderr in separate threads, otherwise you will experience blocking behaviour. 您应该在单独的线程中使用stdout和stderr,否则您将遇到阻塞行为。

I suspect that's what's happening in this instance (and that it's unrelated to cleartool/cleardiff other than they're outputting stdout/err). 我怀疑这是在这种情况下发生的事情(它与cleartool / cleardiff无关,只不过它们输出的是stdout / err)。 See this answer for more information. 有关更多信息,请参见此答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM