Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Java close() stream after a terminal operation is issued?

After reading https://www.airpair.com/java/posts/spring-streams-memory-efficiency, I am tempted to stream results out of a database, but as I discussed with a colleague (cfr. comment he added to that article), one needs to remember to use the try-with-resources construct to avoid any memory leaks.

  1. Why doesn't the Java 8 library take care of closing streams itself after each terminal operation (without having to wrap the stream instantiation in a try-with-resources)?
  2. If applicable, are there any plans for this functionality to be added to Java, or would it make sense to request it?
like image 495
Sébastien Dubois Avatar asked Mar 02 '15 15:03

Sébastien Dubois


People also ask

Does Java automatically close stream?

Streams have a BaseStream. close() method and implement AutoCloseable , but nearly all stream instances do not actually need to be closed after use. Generally, only streams whose source is an IO channel (such as those returned by Files. lines(Path, Charset) ) will require closing.

What happens if you don't close a stream in Java?

IO Resources. Under the hood, this method opens a FileChannel instance and then closes it upon stream closure. Therefore, if we forget to close the stream, the underlying channel will remain open and then we would end up with a resource leak.

What happens if you do not call a terminal operation on a stream?

Non-Terminal operation : will transform a stream into another stream, such as filter(Predicate).

Do we have to close the stream always Java?

Yes you you should close it and you can close it if you pass it into a submethod. If you pass it into a Reader though, if you call close on the Reader it will also close the stream.


1 Answers

Because streams that require explicit resource release is actually a pretty unusual case. So we chose not to burden all stream execution with something that is only valuable for .01% of usages.

We made Stream Autocloseable so that you can release resources from the source if you want to, but this is where we stopped, and for a good reason.

Not only would doing this automagically burden the majority of users with extra work that they don't need, but this would also violate a general principle: he who allocates the resource is responsible for closing the resource. When you call

BufferedReader reader = ... reader.lines().op().op()... 

you are the one opening the resource, not the stream library, and you should close it. In fact, since closing a stream resulting from calling an accessor method on some resource-holding object will sometimes close the underlying object, you probably don't want the stream closing the BufferedReader for you -- you might want it to stay open after the call.

If you want to close the resource, this is easy too:

try (BufferedReader reader = ...) {     reader.lines().op()... } 

You're probably using streams in a particular way, so it probably seems "obvious" what streams should do -- but there are more use cases out there than yours. So rather than catering to specific use cases, we approached it from the general principle: if you opened the stream, and you want it closed, close it yourself, but if you didn't open it, it's not for you to close.

like image 119
Brian Goetz Avatar answered Oct 04 '22 16:10

Brian Goetz