如何监控由ProcessBuilder运行的外部进程?

6
这应该很简单,但我在JavaDocs中没有找到任何有用的信息。

我需要在我的Java代码中运行一些外部进程,并能够监视该进程是否已关闭。换句话说,我希望能够可靠地确定我的外部进程是否未被用户结束。

如果不存在跨平台的解决方案,则我将接受在Linux下工作的任何东西。

我目前的代码片段:

public static void main(String[] args) {
    ProcessBuilder pb = new ProcessBuilder("some proces name");

    try {
        Process p = pb.start();
        // p.isRunning(); <- now, that would be helpful :-)
    } catch (IOException e) {
        e.printStackTrace();
    }
}

你所说的“关闭”与“未被用户结束”是什么意思?你是在谈论错误代码还是其他输出? - Gray
说“由用户结束”可能确实不太准确。我真正想知道的是在任何给定时间进程是否仍在运行。 - ŁukaszBachman
3个回答

7

开启一个新线程,调用Process.waitFor()方法,并在该方法返回时设置一个标记。然后,您可以随时检查该标记,以查看进程是否已完成。

public class ProcMon implements Runnable {

  private final Process _proc;
  private volatile boolean _complete;

  public boolean isComplete() { return _complete; }

  public void run() {
    _proc.waitFor();
    _complete = true;
  }

  public static ProcMon create(Process proc) {
    ProcMon procMon = new ProcMon(proc);
    Thread t = new Thread(procMon);
    t.start();
    return procMon;
  }
}

(省略了一些样板内容)。


5

我不确定我是否理解了这个问题,但是一种方法是调用process.exitValue();。 如果进程尚未终止,则会抛出异常:

/**
 * Returns the exit value for the subprocess.
 *
 * @return  the exit value of the subprocess represented by this 
 *          <code>Process</code> object. by convention, the value 
 *          <code>0</code> indicates normal termination.
 * @exception  IllegalThreadStateException  if the subprocess represented 
 *             by this <code>Process</code> object has not yet terminated.
 */
abstract public int exitValue();

如果你不介意使用hack,那么在工作于一个使用UNIXProcess类的~Unix系统上,你可以像下面这样做。但是,这确实使用了反射:

ProcessBuilder pb = new ProcessBuilder("/bin/sleep", "5");
Process process = pb.start();
// open accessability of the UNIXProcess.hasExited field using reflection
Field field = process.getClass().getDeclaredField("hasExited");
field.setAccessible(true);
// now we can get the field using reflection
while (!(Boolean) field.get(process)) {
    ...
}

我考虑过这个问题,但感觉有点像滥用API。我想知道的是进程是否正在运行,而不是进程终止是否没有发生。我知道它们应该是一样的,但老实说,我期望有一些API组件可以获取现有的“Process”实例,并提供关于该进程内运行线程状态的其他元数据。 - ŁukaszBachman
@ŁukaszBachman 我不认为这是 API 的“滥用”。它只是非布尔条件。我还添加了一种方法来获取 hasExited 内部值,但这是使用反射的黑客技巧。 - Gray
我会选择 waitFor(),但反射的想法也不错。 - ŁukaszBachman

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接