Java 即使InputStream保持打开状态,我是否需要关闭InputStreamReader?

Java 即使InputStream保持打开状态,我是否需要关闭InputStreamReader?,java,memory,memory-management,bufferedreader,inputstreamreader,Java,Memory,Memory Management,Bufferedreader,Inputstreamreader,InputStream作为参数从某个地方传递,在那里它将被进一步处理,然后关闭。所以我不想在这里关闭InputStream。考虑下面的代码: void readInputStream(final InputStream inputStream) { final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line; while

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
在其他地方被关闭,读者也需要关闭吗?不关闭读卡器会导致内存泄漏吗

即使底层的
InputStream
在其他地方关闭,读卡器也需要关闭吗

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

不关闭读卡器会导致内存泄漏吗

不,没有内存泄漏,假设
读卡器本身在您使用完后变得不可访问。此外,
阅读器
通常不会占用大量内存

更重要的问题是,如果不关闭
读卡器
,是否会导致资源泄漏。答案是。。。视情况而定

  • 如果您可以保证底层的
    InputStream
    始终在应用程序中的其他位置关闭,那么就可以解决可能的内存泄漏问题

  • 如果您不能保证这一点,那么就有资源泄漏的风险。底层操作系统级文件描述符在(例如)Linux中是有限的资源。如果JVM不关闭它们,它们可能会耗尽,并且某些系统调用将开始意外失败

但如果确实关闭了
读取器
,则底层的
输入流
将被关闭

InputStream
上多次调用
close()
是无害的,而且几乎不需要任何成本

您不应该关闭
读卡器的唯一情况是关闭底层
InputStream
是错误的。例如,如果关闭一个
SocketInputStream
,应用程序的其余部分可能无法重新建立网络连接。同样,与
系统中的
相关的
输入流
通常无法重新打开

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


@Pshemo提出了系统设计的一个要点

如果您接受一个
InputStream
作为参数,那么使用本地
读取器将其包装可能是错误的。。。尤其是
缓冲读取器
BufferedReader
易于在流上进行预读。如果在方法返回后调用方将使用该流,则任何已读入缓冲区但未被该方法使用的数据都可能丢失


更好的办法是让调用方传递一个
读取器
。或者,应该将此方法记录为拥有
InputStream
。在这种情况下,它应该总是
关闭()
它。

是的,需要关闭读卡器。使用代理,例如,防止关闭传递的参数

void readInputStream(InputStream inputStream) throws IOException{

  try (var bufferedReader = new BufferedReader(new InputStreamReader(
       new CloseShieldInputStream(inputStream)))) {

    String line;
    while ((line = bufferedReader.readLine()) != null) {
      // do my thing
    }
  }
}
JIC:与输入屏蔽类似,Apache Commons I/O还提供了一个输出屏蔽,以解决关闭包装输出流的类似问题,-



有关更详细的考虑,请参考原始答案。@stephen-c的积分

我不完全理解您的问题,但一般来说,是的,这样的资源应该在您使用完之后关闭。另外,我建议您看看try with resources,它会自动为您关闭它们。最后,对于这个问题,您的代码片段不是最合适的。您的方法可能不应该创建自己的
BufferedReader
,而是将其作为参数接受。这样,您的应用程序中将有一个BufferedReader,当不再需要它时可以关闭它,这也将关闭底层的
InputStream
@Pshemo。InputStream被传递给不同的处理程序,这些处理程序使用它做不同的事情。每次之前重置(最后关闭)。只有这个处理程序实际上需要一个BufferedReader,另一个处理程序只是将InputStream传递给库函数等等。我的用例是用户可以上传一个文件,并且这个文件可以由许多不同的处理程序解释。因此,第一个处理程序尝试读取特定格式的文件,如果不是该格式,下一个处理程序将读取该文件,依此类推。每次新处理程序读取inputstream时,都会重置该inputstream。这就是它被传播的原因。但你的回答证实了我的想法,谢谢:)