FileDocCategorySizeDatePackage
ProcessDestroyer.javaAPI DocApache Ant 1.708189Wed Dec 13 06:16:18 GMT 2006org.apache.tools.ant.taskdefs

ProcessDestroyer

public class ProcessDestroyer extends Object implements Runnable
Destroys all registered Processes when the VM exits.
since
Ant 1.5

Fields Summary
private Vector
processes
private Method
addShutdownHookMethod
private Method
removeShutdownHookMethod
private ProcessDestroyerImpl
destroyProcessThread
private boolean
added
private boolean
running
Constructors Summary
public ProcessDestroyer()
Constructs a ProcessDestroyer and obtains Runtime.addShutdownHook() and Runtime.removeShutdownHook() through reflection. The ProcessDestroyer manages a list of processes to be destroyed when the VM exits. If a process is added when the list is empty, this ProcessDestroyer is registered as a shutdown hook. If removing a process results in an empty list, the ProcessDestroyer is removed as a shutdown hook.

        try {
            // check to see if the shutdown hook methods exists
            // (support pre-JDK 1.3 VMs)
            Class[] paramTypes = {Thread.class};
            addShutdownHookMethod =
                Runtime.class.getMethod("addShutdownHook", paramTypes);

            removeShutdownHookMethod =
                Runtime.class.getMethod("removeShutdownHook", paramTypes);
            // wait to add shutdown hook as needed
        } catch (NoSuchMethodException e) {
            // it just won't be added as a shutdown hook... :(
        } catch (Exception e) {
            e.printStackTrace();
        }
    
Methods Summary
public booleanadd(java.lang.Process process)
Returns true if the specified Process was successfully added to the list of processes to destroy upon VM exit.

param
process the process to add
return
true if the specified Process was successfully added

        synchronized (processes) {
            // if this list is empty, register the shutdown hook
            if (processes.size() == 0) {
                addShutdownHook();
            }
            processes.addElement(process);
            return processes.contains(process);
        }
    
private voidaddShutdownHook()
Registers this ProcessDestroyer as a shutdown hook, uses reflection to ensure pre-JDK 1.3 compatibility.

        if (addShutdownHookMethod != null && !running) {
            destroyProcessThread = new ProcessDestroyerImpl();
            Object[] args = {destroyProcessThread};
            try {
                addShutdownHookMethod.invoke(Runtime.getRuntime(), args);
                added = true;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                Throwable t = e.getTargetException();
                if (t != null && t.getClass() == IllegalStateException.class) {
                    // shutdown already is in progress
                    running = true;
                } else {
                    e.printStackTrace();
                }
            }
        }
    
public booleanisAddedAsShutdownHook()
Returns whether or not the ProcessDestroyer is registered as as shutdown hook

return
true if this is currently added as shutdown hook

        return added;
    
public booleanremove(java.lang.Process process)
Returns true if the specified Process was successfully removed from the list of processes to destroy upon VM exit.

param
process the process to remove
return
true if the specified Process was successfully removed

        synchronized (processes) {
            boolean processRemoved = processes.removeElement(process);
            if (processRemoved && processes.size() == 0) {
                removeShutdownHook();
            }
            return processRemoved;
        }
    
private voidremoveShutdownHook()
Removes this ProcessDestroyer as a shutdown hook, uses reflection to ensure pre-JDK 1.3 compatibility

        if (removeShutdownHookMethod != null && added && !running) {
            Object[] args = {destroyProcessThread};
            try {
                Boolean removed =
                    (Boolean) removeShutdownHookMethod.invoke(
                        Runtime.getRuntime(),
                        args);
                if (!removed.booleanValue()) {
                    System.err.println("Could not remove shutdown hook");
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                Throwable t = e.getTargetException();
                if (t != null && t.getClass() == IllegalStateException.class) {
                    // shutdown already is in progress
                    running = true;
                } else {
                    e.printStackTrace();
                }
            }
            // start the hook thread, a unstarted thread may not be
            // eligible for garbage collection
            // Cf.: http://developer.java.sun.com/developer/bugParade/bugs/4533087.html
            destroyProcessThread.setShouldDestroy(false);
            if (!destroyProcessThread.getThreadGroup().isDestroyed()) {
                // start() would throw IllegalThreadStateException from
                // ThreadGroup.add if it were destroyed
                destroyProcessThread.start();
            }
            // this should return quickly, since it basically is a NO-OP.
            try {
                destroyProcessThread.join(20000);
            } catch (InterruptedException ie) {
                // the thread didn't die in time
                // it should not kill any processes unexpectedly
            }
            destroyProcessThread = null;
            added = false;
        }
    
public voidrun()
Invoked by the VM when it is exiting.

        synchronized (processes) {
            running = true;
            Enumeration e = processes.elements();
            while (e.hasMoreElements()) {
                ((Process) e.nextElement()).destroy();
            }
        }