ProcessStreamDrainerpublic class ProcessStreamDrainer extends Object If you don't drain a process' stdout and stderr it will cause a deadlock after a few hundred bytes of output.
At that point the Process is blocked because its stdout and/or stderr buffer is full and it is waiting for the Java caller
to drain it. Meanwhile the Java program is blocked waiting on the external process.
This class makes this common, but messy and tricky, procedure easier.
It creates 2 threads that drain output on stdout and stderr of the external process.
Sample Code:
ProcessBuilder pb = new ProcessBuilder("ls", "-R", "c:/as");
try
{
Process p = pb.start();
ProcessStreamDrainer psd = ProcessStreamDrainer.drain("MyProcess", p);
// or
ProcessStreamDrainer psd = ProcessStreamDrainer.redirect("MyProcess", p);
psd.waitFor(); // this is optional.
}
catch (Exception ex)
{
ex.printStackTrace();
}
|
Fields Summary |
---|
private final Process | process | private final Thread | errThread | private final Thread | outThread | private final String | processName | private final boolean | redirectStandardStreams | private static final String | ERROR_DRAINER | private static final String | OUT_DRAINER |
Constructors Summary |
---|
private ProcessStreamDrainer(String processName, Process process, boolean redirect)
if(process == null)
throw new NullPointerException("Internal Error: null Process object");
this.process = process;
if(processName == null || processName.length() <= 0)
this.processName = "UnknownProcessName";
else
this.processName = processName;
redirectStandardStreams = redirect;
ProcessStreamDrainerWorker worker;
if(redirectStandardStreams)
worker = new ProcessStreamDrainerWorker(process.getInputStream(), System.out);
else
worker = new ProcessStreamDrainerWorker(process.getInputStream());
outThread = new Thread(worker, processName + "-" + OUT_DRAINER);
outThread.setDaemon(true);
if(redirectStandardStreams)
worker = new ProcessStreamDrainerWorker(process.getErrorStream(), System.err);
else
worker = new ProcessStreamDrainerWorker(process.getErrorStream());
errThread = new Thread(worker, processName + "-" + ERROR_DRAINER);
errThread.setDaemon(true);
|
Methods Summary |
---|
public static com.sun.enterprise.util.io.ProcessStreamDrainer | drain(java.lang.String processName, java.lang.Process process)Create an instance and drain the process' stderr and stdout
ProcessStreamDrainer psd = new ProcessStreamDrainer(processName, process, false);
psd.drain();
return psd;
| private void | drain()Start the draining.
We start them here instead of the constructor so that "this" doesn't
leak out of the constructor.
outThread.start();
errThread.start();
| public static com.sun.enterprise.util.io.ProcessStreamDrainer | redirect(java.lang.String processName, java.lang.Process process)Create an instance, drain and redirect the process' stderr and stdout to
System.err and System.out respectively.
ProcessStreamDrainer psd = new ProcessStreamDrainer(processName, process, true);
psd.drain();
return psd;
| public final void | waitFor()Wait for the drain threads to die. This is guaranteed to occur after the
external process dies. Note that this may, of course, block indefinitely.
errThread.join();
outThread.join();
|
|