java - 使用 ProcessBuilder 执行进程会导致挂起 waitFor

标签 java exec

我在使用 Java 运行外部应用程序时遇到问题。我知道输入和输出流的问题,我正在尝试按如下方式阅读它们:

    ProcessBuilder pb = new ProcessBuilder(args);
    args[args.length - 1] += "<NUL";

    pb.redirectErrorStream(true);
    Process p = pb.start();

    InputStreamReader isr = new InputStreamReader(p.getInputStream());
    BufferedReader input = new BufferedReader(isr);
    while (input.readLine() != null) {
    }       

    p.waitFor();
    input.close();
    isr.close();

我正在执行的命令是针对 URL 的 xdg-open,因此它不应该等待输入。

这在我的机器上十分之九有效,但有时它只是卡在 pb.start();并且命令未执行。

java 线程正在等待进程返回。这是堆栈跟踪:

Name: LinkHandlerExec
State: WAITING on java.lang.UNIXProcess$Gate@356122dc
Total blocked: 0  Total waited: 1

Stack trace: 
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:502)
java.lang.UNIXProcess$Gate.waitForExit(UNIXProcess.java:80)
java.lang.UNIXProcess.<init>(UNIXProcess.java:161)
java.lang.ProcessImpl.start(ProcessImpl.java:81)
java.lang.ProcessBuilder.start(ProcessBuilder.java:468)

这是 strace 告诉我的内容:

$ sudo strace -p 13255
Process 13255 attached - interrupt to quit
futex(0x7fbb673e49d0, FUTEX_WAIT, 13262, NULL

最佳答案

我们在 CentOS 6.3 JDK 1.6.0_33-b03 上也观察到这个问题。 调查表明,这是在该 Java 进程发生 OutOfMemoryError 之后发生的。

查看类 java.lang.UNIXProcess 的代码,我想当在 UNIXProcess 构造函数中运行的单独线程中抛出非 IO 异常(例如错误)时,可能会发生此类问题,位于第 109 行和第 130 行之间. 这段代码最好组织成

try {
  .....
} finally {
  gate.exit();
}

,而是组织为

try {
  ...
} catch (IOException e) {
  gate.setException(e); /*remember to rethrow later*/
  gate.exit();
  return;
}
...
gate.exit(); 

,所以一个非IO异常可能导致gate.exit()没有被调用,导致主调用线程在gate.waitForExit()方法(第145行)中永远挂起。

关于java - 使用 ProcessBuilder 执行进程会导致挂起 waitFor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11756267/

相关文章:

Java反序列化和ArrayList奇怪的异常

java - 从 PagedList 中排除重复数据

java - 带有 bouncycaSTLe 的随机损坏的垫 block

java - 替换java中的时间值

java - 为什么我使用 for 循环得到这个结果? [Java]

process - 执行任何 bash 命令,立即获取 stdout/stderr 的结果并使用 stdin

Python EXEC 显示错误 : name is not defined

c - 没有结果!!使用 fork() 使用 dup2 运行带有 2 个管道的 execlp()

java - 如何向 Runtime.exec() 添加超时但检查退出值?

haskell - 干净地替换当前的 Haskell 进程 (exec)