从 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的主要内容,如果未能解决你的问题,请参考以下文章
IllegalStateException:已为此请求调用 getInputStream()
文件上传 servlet 从HttpServletRequest.getInputStream()中获得消息内容
文件上传 servlet 从HttpServletRequest.getInputStream()中获得消息内容