是否需要手动销毁并关闭java.lang.Process的开放流?
Is it required to manually destroy and close the open streams of a java.lang.Process?
我有以下代码:
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?
}
我试图找到一些来源表明是否需要调用 proc.destroy()
(我应该在调用 destroy 之前检查 isAlive()
吗?),并手动关闭它的 input/output/error流,无济于事。据我所知,甚至官方文档也没有明确说明这一点。
当我完成生成的进程时执行这些操作是否有必要,甚至只是一种好的做法?
最好在 finally 块中调用 process.destroyForcibly()
。 waitFor
如果进程没有在超时前完成,则不会终止该进程,因此在生成的进程无限期挂起的情况下,如果您不终止它,它可能会永远存在。
另一个用例是假设您的进程需要大约 25 秒才能正常终止。假设您的线程在启动后几乎立即被中断。最好终止进程而不是一直保留它 运行,因为无论如何都不会使用结果。
关于流,请参阅 Properly closing Java Process InputStream from getInputStream
虽然 正确地解决了答案的“销毁”部分,并且我回应了建议使用 finally
块的建议,但原始问题还询问了有关关闭流的问题,并且有一个微妙的问题差异。
在 Linux、macOS 和 BSD Unix 平台上,destroy()
实现会自动关闭流,因此对于这些平台来说,只需销毁进程并获得流关闭就足够了.
但是,在 Windows 和 Solaris (SunOS) 平台上,本机 destroy()
实现仅执行 TerminateProcess
或 kill
并且不会关闭流。 JDK8 source code.
中甚至还有一个 StreamsSurviveDestroy
测试用例(仅限 Solaris)
因此,如果您在代码中支持 Windows 或 Solaris,除了添加 destroy()
或 destroyForcibly()
之外,您还应该尝试关闭输入、输出和错误流在 finally
块中调用。此流关闭可以在销毁调用之前或之后完成。
我有以下代码:
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?
}
我试图找到一些来源表明是否需要调用 proc.destroy()
(我应该在调用 destroy 之前检查 isAlive()
吗?),并手动关闭它的 input/output/error流,无济于事。据我所知,甚至官方文档也没有明确说明这一点。
当我完成生成的进程时执行这些操作是否有必要,甚至只是一种好的做法?
最好在 finally 块中调用 process.destroyForcibly()
。 waitFor
如果进程没有在超时前完成,则不会终止该进程,因此在生成的进程无限期挂起的情况下,如果您不终止它,它可能会永远存在。
另一个用例是假设您的进程需要大约 25 秒才能正常终止。假设您的线程在启动后几乎立即被中断。最好终止进程而不是一直保留它 运行,因为无论如何都不会使用结果。
关于流,请参阅 Properly closing Java Process InputStream from getInputStream
虽然 finally
块的建议,但原始问题还询问了有关关闭流的问题,并且有一个微妙的问题差异。
在 Linux、macOS 和 BSD Unix 平台上,destroy()
实现会自动关闭流,因此对于这些平台来说,只需销毁进程并获得流关闭就足够了.
但是,在 Windows 和 Solaris (SunOS) 平台上,本机 destroy()
实现仅执行 TerminateProcess
或 kill
并且不会关闭流。 JDK8 source code.
StreamsSurviveDestroy
测试用例(仅限 Solaris)
因此,如果您在代码中支持 Windows 或 Solaris,除了添加 destroy()
或 destroyForcibly()
之外,您还应该尝试关闭输入、输出和错误流在 finally
块中调用。此流关闭可以在销毁调用之前或之后完成。