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

ent*_*enr 2 java memory memory-management bufferedreader inputstreamreader

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
    }
}
Run Code Online (Sandbox Code Playgroud)

根据另一个Stackoverflow帖子,如果我关闭BufferedReaderand和/或the InputStreamReader,那么底层InputStream也将被关闭。

我的问题:即使底层InputStream在其他地方关闭,读者也需要关闭吗?如果不关闭阅读器,是否会发生内存泄漏?

Ste*_*n C 5

读者是否需要关闭,即使底层InputStream关闭了其他地方?

不,他们绝对不需要处于那种情况下。但无论如何,将它们关闭通常是一个好主意。

如果不关闭阅读器,是否会发生内存泄漏?

不,没有内存泄漏,前提是Reader一旦完成,内存本身就无法访问。此外,a Reader通常不会占用大量内存。

更为重要的问题是,如果不关闭,是否会导致资源泄漏Reader。答案是……这取决于。

  • 如果你能保证底层InputStream总是会在应用程序中其他地方关闭,然后采取的可能的内存泄漏的照顾。

  • 如果不能保证,则存在资源泄漏的风险。底层操作系统级别的文件描述符是(例如)Linux中的有限资源。如果JVM无法关闭它们,它们可能会用完,并且某些系统调用将开始意外失败。

但是,如果您确实关闭,Reader则基础InputStream 被关闭。

close()多次调用a InputStream是无害的,而且几乎不花任何费用。

唯一不应该关闭的情况Reader是关闭底层证券是错误的InputStream。例如,如果您关闭SocketInputStream其余的应用程序,则可能无法重新建立网络连接。同样,与InputStream关联的对象System.in通常无法重新打开。

在这种情况下,实际上可以安全地允许Reader您在方法中创建的对象进行垃圾回收。不同于InputStream,典型的Reader类不会重写Object::finalize()以关闭其数据源。


@Pshemo提出了有关系统设计的重点。

如果您接受an InputStream作为参数,那么用local Reader... 包裹它可能是错误的,尤其是a BufferedReader。A BufferedReader可能会在流中预读。如果您的方法返回该流将由调用方使用,则任何已读入缓冲区但未被该方法使用的数据都可能会丢失。

更好的主意是让呼叫者传递一个Reader。另外,此方法应记录为取得所有权InputStream。在这种情况下,应该始终close()如此。