即使InputStream应该保持打开,我还需要关闭InputStreamReader吗?

问题描述 投票:1回答:1

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在其他地方关闭了?不关闭读者会导致内存泄漏吗?

java memory memory-management bufferedreader inputstreamreader
1个回答
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()它。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.