Home > Software > Detecting process exit in Java

Detecting process exit in Java


If you develop a more complex system, the chances of being a heterogeneous are pretty big. So if you develop a system in Java, but you have to integrate all ready build parts with other technology, the most desirable option is some kind of service oriented architecture. But when this is not available you will simply rely on an external process.
To start an external process is quite simple. Just look at the exec methods from Runtime.
What could be more difficult is to know when that process as finished. The Java process and that subprocess will run in parallel. If you want to perform an action when the subprocess has finish its execution, this article may help you in this direction.
It would be very nice if the Process class would implement the Observable design pattern in some way. But it doesn’t and on this we will base our workaround creation.
Process contains a useful method for us, waitFor, that pauses the current thread execution until the given subprocess is finished. So, we will create a thread that will be suspended until the given subprocess is finished. Then we will fire the listeners to notify that the process has finished its execution.
Enough talking, let’s see some code.

/**
 * Detects when a process is finished and invokes the associated listeners.
 */
public class ProcessExitDetector extends Thread {

    /** The process for which we have to detect the end. */
    private Process process;
    /** The associated listeners to be invoked at the end of the process. */
    private List<ProcessListener> listeners = new ArrayList<ProcessListener>();

    /**
     * Starts the detection for the given process
     * @param process the process for which we have to detect when it is finished
     */
    public ProcessExitDetector(Process process) {
        try {
            // test if the process is finished
            process.exitValue();
            throw new IllegalArgumentException("The process is already ended");
        } catch (IllegalThreadStateException exc) {
            this.process = process;
        }
    }

    /** @return the process that it is watched by this detector. */
    public Process getProcess() {
        return process;
    }

    public void run() {
        try {
            // wait for the process to finish
            process.waitFor();
            // invokes the listeners
            for (ProcessListener listener : listeners) {
                listener.processFinished(process);
            }
        } catch (InterruptedException e) {
        }
    }

    /** Adds a process listener.
     * @param listener the listener to be added
     */
    public void addProcessListener(ProcessListener listener) {
        listeners.add(listener);
    }

    /** Removes a process listener.
     * @param listener the listener to be removed
     */
    public void removeProcessListener(ProcessListener listener) {
        listeners.remove(listener);
    }
}

The code is very easy to understand. It creates a class as the detector for the process exit. It has a process to watch for passed in as a constructor argument. The entire thread does nothing else than wait for the given process to finish and then invokes the listeners.
The code for the ProcessListener is as easy:

public interface ProcessListener extends EventListener {
    void processFinished(Process process);
}

Now you have a very easy way to detect when a subprocess is finished, and as proof, here is a code sample:

    // ...
    processExitDetector = new ProcessExitDetector(subprocess);
    processExitDetector .addProcessListener(new ProcessListener() {
        public void processFinished(Process process) {
            System.out.println("The subprocess has finished.");
        }
    });
    processExitDetector.start();
    // ...

.
All the code samples were tested with JDK 6 under Windows XP.

Categories: Software Tags:
  1. veitner
    November 5, 2008 at 5:08 pm

    Hi,

    somewhat useful – thank you.

    Have you got any idea how to pause and resume a process spawned by ProcessBuilder (the pid is declared private in UNIXProcess)?

  2. November 6, 2008 at 4:54 pm

    Pause and resume? Hmm, I don’t think there is any way to do this in a portable manner, unless you’re using some JNI code.

  3. Rene
    February 4, 2009 at 9:54 am

    Hi,

    Thnk you for this contribution.

    Can we detect when the main process has exited (for instance to save all open frames)

  4. February 4, 2009 at 11:12 am

    The main process is practically the JVM process. Just use Runtime.addShutdownHook().

  5. Tozak
    September 10, 2009 at 8:45 pm

    Adrian,

    I have an implementation that matches your idea but its not working for a particular case. I’m launching a Windows application (let’s call it winapp1) via the cmd shell. Winapp1 further spawns 2 threads and launches winapp2 via each thread. However, winapp1 returns immediately while the 2 copies of winapp2 are still active. My Java app that started winapp1 was blocked on the waitFor() call for the process that started winapp1. This process returns immediately and my java app shows the work as done. In reality the work is still being done by the 2 sub-processes (winapp2). I’ve looked at the Runtime class but didn’t find anything that may help with this situation. Any ideas?

    Thanks,

    Tozak

  6. September 11, 2009 at 5:10 pm

    I don’t think you can use the method presented above in your case. If you own winapp2, then some kind of socket communication will be an option.

  7. kevin
    January 25, 2010 at 9:52 pm

    Adrain, can i have complete the example..
    I have complile error at
    for (ProcessListener listener : listeners) {

    can you email me at codonneem@gmail.com

    Hope to hear you soon..

  8. January 26, 2010 at 5:51 am

    I corrected the example. Please try it again.

  9. Anonymous
    December 8, 2011 at 1:21 pm

    Thank you very much for this very nice example…………..

  10. ranilo ignacio
    June 23, 2012 at 1:45 pm

    thanks very much, this works well 🙂
    I haven’t thought much that this kind of listener were available or very straightforward indeed

  11. al
    January 25, 2013 at 10:14 am

    Adrian, like kevin said before, mysteriously on my eclipse i am having an unresolved compilation error are you sure this is the correct code, because i am having lots of unresolved issues on my project. I sort of now made all my other process programs dependent on this listener because i heard it was good. My entire program is sort of now blocked because of the code error. My eclipse software doesn’t recognize the &lt and the > and it doesn’t recognize the for (ProcessListener listener : listeners) { or the addProcessListener(ProcessListener listener) {, email me back at alexincupertino@gmail.com. Thank you.

  12. February 6, 2013 at 3:54 pm

    good article. i would like to ask how could i use waitFor() if the process is done manually. My problem is I have to install an application manually (e.g. Skype) and then let java know once this the applications has already been installed and the process is done. is there a way to do this?

  1. No trackbacks yet.

Leave a comment