从 getInputStream 正确关闭 Java Process InputStream

Posted

技术标签:

【中文标题】从 getInputStream 正确关闭 Java Process InputStream【英文标题】:Properly closing Java Process InputStream from getInputStream 【发布时间】:2011-10-29 04:31:03 【问题描述】:

我无法在文档中找到对此的说明。 但是当我们有一个Process 对象并调用getInputStream() 时,

我们是否得到了一个新的流,我们应该在完成后明确关闭它? 要么 我们是否获得了与 Process 相关联的已经存在的流,我们不应该关闭它,但 Process 会负责关闭它?

基本上,我们应该如何与从Process.getInputStream() 获得的流进行交互?关还是不关?

【问题讨论】:

【参考方案1】:

通过阅读 UNIXProcess.java,会发生以下情况:

我们需要区分两种状态:要么进程还活着,要么已经死了。

如果进程处于活动状态,通过关闭 OutputStream(转到进程的标准输入),您是在告诉进程没有更多输入。通过关闭 InputStreams(进程的stdout、stderr),进程不再向这些写入(如果尝试它会得到SIGPIPE)。

当进程死亡时,Java 将缓冲来自 stdout/stderr 的剩余数据,并为您关闭所有三个流(它正在运行“进程收割机”线程,该线程会在进程死亡时得到通知)。任何写入 OutputStream 的尝试都将失败。从 InputStream 读取将返回缓冲数据(如果有)。关闭其中任何一个都没有好处,但也不会造成任何伤害。 (此时底层文件描述符已关闭)。

【讨论】:

你能备份一下吗?这是一个有趣的主题,你的回答有细节。谢谢。 关闭 InputStream 是否肯定会清除缓冲区?即如果进程已死,但缓冲区中有未读数据,是否在关闭 InputStream 时肯定会从缓冲区中删除?【参考方案2】:

我的第一反应是关闭它,你总是关闭你打开的流。我确实意识到文档没有达到标准,但由于他们没有明确声明不要关闭,这对我来说意味着遵循良好的编程实践。

InputStream is = process.getInputStream()
try 
    // your code
 finally 
    try  is.close();  catch (Exception ignore) 

如果您需要确保这没有问题,只需编写一个快速测试用例,您可以从输入流中多次打开和关闭 InputStream。

【讨论】:

IOUtils.closeQuietly(is) 将处理 try is.close(); 捕捉(异常忽略)【参考方案3】:

当您调用Process.getInputStream() 时,您会得到一个为进程设置的现有输入流。当进程终止时,输入流不会自动消失 - 将其视为您仍然可以从中读取的缓冲区。进程的管道末端可能已关闭,但您的末端不是。关闭它是你的责任,尽管 GC 最终会得到它。

您还应该关闭另外两个:getErrorStream()getOutputStream()

【讨论】:

“当进程终止时,输入流不会自动消失”——当你启动一个进程时,Java 正在运行“进程收割机”线程,它会在此关闭此类管道的本地端案例。【参考方案4】:

你没有关闭流,你没有打开 - 这是一个令人讨厌的副作用。 如果您创建了该进程,请先将其终止,然后再关闭流。

【讨论】:

【参考方案5】:

我总是关闭它们!我不是 100% 确定,但据我所知,如果您打开输入流,文件将一直打开,直到您关闭它!所以遵循“标准规则”并关闭它!举个例子: Process Builder waitFor() issue and Open file limitations

【讨论】:

以上是关于从 getInputStream 正确关闭 Java Process InputStream的主要内容,如果未能解决你的问题,请参考以下文章

Java代码启动/关闭进程

IllegalStateException:已为此请求调用 getInputStream()

文件上传 servlet 从HttpServletRequest.getInputStream()中获得消息内容

文件上传 servlet 从HttpServletRequest.getInputStream()中获得消息内容

HttpURLConnection.getInputStream() 挂起并且永远不会完成

测试扩展——javaweb文件上传逻辑