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

时间:2015-10-22 07:47:10

标签: 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.")
 }
...
}

在这里,一旦我完成了流,我将退出myMethod(),但程序反过来进程,不会终止并继续进行其他操作。

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

感谢任何帮助!

7 个答案:

答案 0 :(得分:11)

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

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

有操作系统可以检查打开的文件和流,例如lsof

答案 1 :(得分:4)

如果您没有手动压缩它,那么当进程终止时,将释放所有非托管资源,但这不是推荐的或最佳做法。完成后,您应该始终关闭流。

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

try (InputStream input = new FileInputStream(...);
     Reader reader = new InputStreamReader(input, ...)) {
   ...
}
  

我没有关闭溪流。它会自动关闭吗?   A类的引用范围结束了吗?

不,它不会自动关闭。

以下是一个很好的参考:

Better Resource Management with Java SE 7: Beyond Syntactic Sugar

答案 2 :(得分:3)

FileInputStream的情况下,有一个finalize()方法,当流被垃圾收集时,它将释放资源。

不是说你可以或应该依赖它。这正是FileInputStream的作用。另一方面,SocketInputStream会覆盖finalize()以明确不执行任何操作,依靠Socket关闭资源(而Socket没有finalize()方法)

答案 3 :(得分:1)

只要JVM正在运行,就无法保证资源将被关闭。您建议的实现非常危险。

我会建议什么。 使类A成为Closeable并使用Java的tryResourceClose-Statement。 这个例子在这里。 https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

离开try-block后,您将有机会关闭资源。

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

答案 4 :(得分:0)

这是一个糟糕的编程习惯,程序员的错误。根据底层数据源,它可能永远不会关闭,您可能会有泄漏。当你完成它,在finally块中,或者使用Java 7或更高版本的资源尝试时,你必须关闭任何资源,以确保即使抛出异常也关闭它。

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

答案 5 :(得分:0)

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

您可以查看thisjava doc了解更多信息

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构造中使用。

答案 6 :(得分:0)

说在过程结束时将清除资源是不正确的。开放资源是第一手的系统调用。该进程主要是Java进程,而不是OS进程,取决于底层OS。因此,通常来说,由于JVM无法保证操作系统的系统调用所必需的此类操作,因此,如果您不关闭流,则资源请求的状态不确定,因此资源是确定的,因为Java无法保证关于它,尝试资源恰好是此的简写。但是50%的人不会关闭流。