Is it required to manually destroy and close the open streams of a java.lang.Process?
Asked Answered
S

2

5

I have the following code:

Process proc;
try
{
    ProcessBuilder procBuilder = new ProcessBuilder(/* some args */);
    proc = procBuilder.start();
    if (proc.waitFor(30000, TimeUnit.MILLISECONDS))
    {
        //Etc...
    }
    else
    {
        //Handle it
    }
}
catch (InterruptedException ie)
{
    currentThread().interrupt();
}
finally
{
    //What goes here?
}

I have tried to find some source that indicates whether it is required to call proc.destroy() (should I check isAlive() before calling destroy?), and to manually close its input/output/error streams, to no avail. Not even the official documentation makes this clear, from what I can tell.

Is it necessary, or even just good practice, to perform these operations when I am finished with the spawned process?

Sukkah answered 29/6, 2020 at 21:47 Comment(2)
You should certainly close the output stream to the process. Otherwise it may block waiting for end of stream on its stdin.Greatcoat
If the process generates output, you need to do something with it. If you don’t care about the output, use procBuilder.inheritIO(); (before starting the process) to make it appear in the same place as your Java program’s output.Homestretch
H
4

It's a good idea to call process.destroyForcibly() in the finally block. waitFor will not kill the process if it does not finish before the timeout, so in a situation where the spawned process hangs indefinitely, if you do not kill it then it could stick around forever.

Another use-case is suppose your process takes around 25 seconds to terminate normally. Suppose your thread is interrupted almost immediately after starting. It's probably better to kill the process rather than leave it running all that time, since the result will never be used anyway.

As for the streams, see Properly closing Java Process InputStream from getInputStream

Huey answered 29/6, 2020 at 22:20 Comment(0)
H
3

While Michael's answer correctly addresses the "destroy" part of the answer and I echo the advice to use a finally block as suggested, the original question also asked about closing streams and there's a subtle difference.

On Linux, macOS, and BSD Unix platforms, the destroy() implementations close the streams automatically, so for these platforms it is sufficient to just destroy the process and get the stream closures as well.

However, on the Windows and Solaris (SunOS) platforms, the native destroy() implementation simply executes TerminateProcess or kill and does not close the streams. There is even a StreamsSurviveDestroy test case (Solaris-only) in the JDK8 source code.

So if you are supporting Windows or Solaris in your code, you should attempt to close the input, output, and error streams in addition to adding a destroy() or destroyForcibly() call in a finally block. This stream closure can be done either before or after the destroy call.

Hensel answered 24/11, 2021 at 23:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.