InputStream
作为参数从某个地方传递,在那里将被进一步处理然后关闭。因此,我不想在这里关闭InputStream
。考虑以下代码:
void readInputStream(final InputStream inputStream) {
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine() != null) {
// do my thing
}
}
根据另一Stackoverflow帖子,如果我关闭BufferedReader
和/或InputStreamReader
,则基础InputStream
也将关闭。
我的问题:即使底层的InputStream
在其他地方关闭,读者也需要关闭吗?我可以通过不关闭阅读器来获取内存泄漏吗?
答案 0 :(得分:4)
即使底层的
InputStream
在其他地方已经关闭,读者也需要关闭吗?
不,在这种情况下,他们绝对不需要。但无论如何,将它们关闭通常是一个好主意。
是否可以通过不关闭阅读器来导致内存泄漏?
否,假设Reader
本身一旦完成就无法访问,就没有内存泄漏。此外,Reader
通常不会占用大量内存。
更重要的问题是,是否可以通过不关闭Reader
来获得资源泄漏。答案是……取决于。
如果您可以保证基础InputStream
始终会在应用程序中的其他位置关闭,那么 可以解决可能的内存泄漏。
如果不能保证,则存在资源泄漏的风险。底层操作系统级别的文件描述符是(例如)Linux中的有限资源。如果JVM无法关闭它们,它们将耗尽,并且某些系统调用将意外失败。
但是如果您执行关闭Reader
,则基础InputStream
将被关闭。
在close()
上多次调用InputStream
是无害的,而且几乎不花任何费用。
唯一不关闭Reader
的情况是关闭基础InputStream
是错误的。例如,如果关闭SocketInputStream
,则该应用程序的其余部分可能无法重新建立网络连接。同样,与InputStream
关联的System.in
通常无法重新打开。
在这种情况下,实际上可以安全地对在方法中创建的Reader
进行垃圾回收。与InputStream
不同,典型的Reader
类不会覆盖Object::finalize()
来关闭其数据源。
@Pshemo提出了有关系统设计的重要观点。
如果您接受InputStream
作为参数,那么用本地Reader
...(尤其是BufferedReader
)包装它可能是错误的。 `BufferedReader易于在流上预读。如果流将由调用方之后使用,则您的方法将返回,那么任何已读入缓冲区但未被此方法使用的数据都可能会丢失。
一个更好的主意是呼叫者传递一个Reader
。另外,此方法应记录为InputStream
的“拥有所有权”。在这种情况下,应该始终close()
。
答案 1 :(得分:1)
是的,读者需要关闭。使用代理,例如CloseShieldInputStream,以防止关闭传递的参数。
html %>% xml2::read_html() %>% html_nodes(xpath = safe_xpath(target))
#> {xml_nodeset (1)}
#> [1] <div>Fat"her's son</div>
JIC :类似于输入屏蔽,Apache Commons I / O还提供了输出屏蔽来解决类似的问题,即关闭包装输出流-CloseShieldOutputStream
有关更详细的注意事项,请参阅原始答案。归功于@ stephen-c