When does a stream close if its not closed manuall

2020-03-01 16:33发布

问题:

I would like to know when does a stream close if its not closed manually. By this I mean, will the stream be closed if the scope of its reference is no more?

Consider the following sample scenario.

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

Here, once I am done with the stream, I am exiting myMethod() but the program which in turn the process, is not terminated and goes on with other operations.

I did not close the streams. Will it be closed automatically once the scope of the reference to class A ends? (ie. When myMethod() ends)? Does GC takes care of that? Also, I read that the streams will be closed once the process ends and the system releases all the resources held for it for other processes. How can we check whether the stream is open or not? Are there any linux commands or options from Java to check that?

Any help is appreciated!

回答1:

I don't think that the JVM spec makes any guarantee about that. You really are supposed to finally close these resources.

When the process ends, the operating system will release all resources associated to it (including memory, file handles, and network sockets).

There are OS facilities to check about open files and streams, such as lsof.



回答2:

If you are not clossing it manually then all the unmanaged resources will be released when the process termiantes, however it is not a recommended or a best practice. You should always close your stream once you are done with it.

A better and suggested way to manage the stream is to use try with resource option like this:

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

I did not close the streams. Will it be closed automatically once the scope of the reference to class A ends?

No it will not close automatically.

A good reference to follow is:

Better Resource Management with Java SE 7: Beyond Syntactic Sugar



回答3:

In the case of FileInputStream there's a finalize() method that will free resources when the stream is garbage collected.

Not that you can or should rely on that. It's just what FileInputStream does. SocketInputStream on the other hand overrides finalize() to explicitly do nothing, relying on Socket to close the resources (and Socket doesn't have a finalize() method).



回答4:

There is no garantee that the resources will be closd as long as the JVM is running, Your suggested implementation is quite dangerous.

What I would suggest. Make the class A a Closeable and use the tryResourceClose-Statement of Java. The example is here. https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

After leaving the try-block you get the chance to close your resources.

The stream itself normally doesn't know if it is open or not. However, your own class A can keep track it the streams were closed or not.



回答5:

That's a bad programming practice, an error from the programmer. Depending on the underlying data source, it might never close and you can have leaks. You MUST close any resource when you've finished with it, in a finally block, or using a try with resources if Java 7 or higher, to ensure it is closed even if an exception is thrown.

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


回答6:

With Java 7, you can create one or more “resources” in the try statement. A “resources” is something that implements the java.lang.AutoCloseable interface. This resource would be automatically closed and the end of the try block.

you can look this and java doc for more info

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();
        }
    }
}

When the try block finishes the FileInputStream will be closed automatically. This is possible because FileInputStream implements the Java interface java.lang.AutoCloseable. All classes implementing this interface can be used inside the try-with-resources construct.



回答7:

It is not correct to say that when the process ends that the resources will be cleaned up. An open resource is a system call firsthand. The process is primarily the java process and not an OS process, depends on the underlying OS. So in general as the JVM cannot make guarantees of such operations that are fundamental to the system call of the OS, the state of a resource request is undetermined if you don't close a stream, thereby the resource deterministically, as Java cannot make guarantees about it, try resource was exactly a shorthand for this. But 50% don't close streams. .