6

This should be rather simple, but I don't see anything helpful in JavaDocs.

What I need is to run some external process from my Java code and then be able to monitor if this process has been shutdown or not. In other words, I want to be able to reliably determine whether or not my external process was not ended by user.

If no cross platform solution exists, I will accept anything working under Linux.

My current snippet of code:

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
  • 115,027
  • 24
  • 293
  • 354
ŁukaszBachman
  • 33,595
  • 11
  • 64
  • 74
  • What do you mean "shutdown" versus "not ended by user". Are you talking about an error code or some other output? – Gray Jul 16 '12 at 18:37
  • Well, saying "ended by user" might not indeed be that accurate. What I really want to know is if the process is still running at any given time. – ŁukaszBachman Jul 16 '12 at 18:45

3 Answers3

7

Start a new Thread which calls Process.waitFor() and sets a flag when that call returns. then, you can check that flag whenever you want to see if the process has completed.

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

(some boilerplate omitted).

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
5

I'm not sure I'm understanding the question but one way to do this is to call process.exitValue();. It throws an exception if process has not yet terminated:

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

If you don't mind a hack, you can do something like the following if you are working on a ~Unix system which uses the UNIXProcess class. This does use reflection however:

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)) {
    ...
}
Gray
  • 115,027
  • 24
  • 293
  • 354
  • Thought about it, but this sounds a little bit like API 'abuse'. I would like to know if the process is running, not if the process termination didn't happen. I know that it should be the same, but honestly I was expecting some API component which would take existing `Process` instance and could provide some additional metadata regarding the status of thread running within that process. – ŁukaszBachman Jul 16 '12 at 18:49
  • @ŁukaszBachman I would not consider this to be API "abuse" at all. All it is is the not-boolean condition. I've also added a way to get to the `hasExited` internal value but it is a hack that uses reflection. – Gray Jul 16 '12 at 18:51
  • I will go with `waitFor()`, but +1 for reflection idea. – ŁukaszBachman Jul 16 '12 at 18:57
2

Based on the question's specific code snippet I might be useful to add that since 1.8 the Process class has an isAlive() method is available

Documentation link: https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html

good luck to anyone reading this!