Java 如果未手动关闭流,则流何时关闭?

Java 如果未手动关闭流,则流何时关闭?,java,stream,inputstream,outputstream,Java,Stream,Inputstream,Outputstream,我想知道如果不是手动关闭,流何时关闭。我的意思是,如果流的引用范围不再存在,流是否会被关闭 考虑以下示例场景 Class A{ InputStream in; OutputStream out; A(){ // Initialize and create the streams. } ... } Class B{ public void myMethod(){ A a = new A(); System.out.println("End of my method.") }

我想知道如果不是手动关闭,流何时关闭。我的意思是,如果流的引用范围不再存在,流是否会被关闭

考虑以下示例场景

Class A{
 InputStream in;
 OutputStream out;
 A(){
  // Initialize and create the streams.
 }
 ...
}
Class B{
 public void myMethod(){
 A a = new A();
 System.out.println("End of my method.")
 }
...
}
在这里,一旦我处理完流,我将退出
myMethod()
,但程序不会终止,而是继续执行其他操作

我没有关闭溪流。一旦A类参考范围结束,它是否会自动关闭?(即当
myMethod()
结束时)?GC负责吗?此外,我还了解到,一旦流程结束,系统将关闭流,并为其他流程释放为其保留的所有资源。我们如何检查流是否打开?是否有来自Java的linux命令或选项来检查这一点


感谢您的帮助

我认为JVM规范对此没有任何保证。你真的应该
最终关闭这些资源

当进程结束时,操作系统将释放与其相关的所有资源(包括内存、文件句柄和网络套接字)


有一些操作系统工具可以检查打开的文件和流,例如。

这是一种糟糕的编程实践,是程序员的错误。根据基础数据源的不同,它可能永远不会关闭,并且可能存在泄漏。当您使用完任何资源后,必须在
finally
块中关闭该资源,或者在Java 7或更高版本中使用try with resources,以确保即使引发异常也能关闭该资源

InputStream in;
OutputStream out;
try {
   // Do your stuff with the streams
} finally {
   if (in != null) {
       in.close();
   }
   if (out != null) {
       out.close();
   }
}

如果您不是手动关闭它,那么当流程终止时,所有非托管资源都将被释放,但是这不是推荐的或最佳实践。您应该始终关闭您的流,一旦您完成它

管理流的一种更好的建议方法是使用try with resource选项,如下所示:

try (InputStream input = new FileInputStream(...);
     Reader reader = new InputStreamReader(input, ...)) {
   ...
}
我没有关闭溪流。一旦关闭,它会自动关闭吗 A类的参考范围结束了吗

不,它不会自动关闭

以下是一个很好的参考:


FileInputStream
的情况下,有一种
finalize()
方法,在垃圾收集流时释放资源


这并不是说你可以也不应该依赖它。这正是
FileInputStream
所做的<另一方面,code>SocketInputStream
重写
finalize()
而不显式执行任何操作,依靠
Socket
关闭资源(并且
Socket
没有
finalize()
方法)。

使用Java 7,您可以在try语句中创建一个或多个“资源”。“资源”是实现java.lang.AutoCloseable接口的东西。此资源将自动关闭,并在try块结束时关闭

您可以查看和获取更多信息

private static void printFileJava7() throws IOException {

    try(FileInputStream input = new FileInputStream("file.txt")) {

        int data = input.read();
        while(data != -1){
            System.out.print((char) data);
            data = input.read();
        }
    }
}

当try块完成时,FileInputStream将自动关闭。这是可能的,因为FileInputStream实现了Java接口Java.lang.AutoCloseable。实现此接口的所有类都可以在try-with-resources构造中使用。

不能保证只要JVM运行,资源就会被关闭,您建议的实现是非常危险的

我的建议。 使类A成为可关闭的,并使用Java的tryResourceClose语句。 这里就是一个例子。

离开try区块后,您有机会关闭资源

流本身通常不知道它是否打开。
但是,您自己的类A可以跟踪流是否已关闭。

作为一项规则,您应该始终在
最后
块中关闭所有流(通常包括可关闭的流)块(或尝试使用资源)此时,我坐在椅子上,试图记住我打开的所有Java流,我假设他们自动关闭了这个范围。过去15年。然后,我站起来尖叫“C++我爱你那么深”。是的,我在
最后
块中关闭它,但出于好奇问。但是你不认为GC也应该被配置来处理这个问题吗?因为,一旦引用的作用域结束,它引用的所有流以及内存都应该被垃圾收集。是吗?是的,GC最终会发生。但不能保证它是及时的,也不能完全保证运行终结器(这将关闭流)。他们的立场是,开发人员应该处理好它。