I have two threads in Java.
First thread is closing a bufferedreader (br.close())
When the second thread does a read on the same reader I get an IOException (Stream Closed)
I get this exception even if I use br.ready()
Is there a way to know if the stream is already closed?
The method ready() will throw an exception if closed. But even if you added a closed check method, so long as the lock is released between calls (which it is for BufferedReader), the reader might be closed by the time you read it.
I see three options:
Wrap your read call with a try/catch block to handle the closed case.
Create a subclass of BufferedReader that extends close() to set your own variable that
can be used to check to see if the reader is closed. This also requires overriding a lot of
methods to do whatever the behavior you want with a closed reader if you want it do something beside throw the IOException.
Add a lock of your own and use it to both close the reader (one thread) and
check that the buffer is ready and read from it. You can either set a variable directly for the check or just group the ready() and read() calls into the same synchronized block.
I don't think there's any method you can call directly to tell if a stream is closed.
If you really need to have two threads sharing this reader, your best option might be to have the one thread call back to the other thread or set a flag to notify it that the stream has been closed so the other thread knows not to try to read from it.
If you have already started a read operation, then you will notified with an IOException that a stream is closed. Even if you have called br.ready() before, the exception is happening when your code is blocked at the read method.
There is no way to avoid this. On the contrary, you should expect a read operation to throw an exception and be prepared to handle it appropriately.
Another way would be to extend a BufferedReader in your own class, overriding close() method to indicate if it was closed.
Indeed, looking at ensureOpen() it checks if the in object is not null.
Since it is private we can't access it from outside.
But if you really need it, you can use reflection.
BufferedReader myBR = new BufferedReader(new FileReader("c:/somefile.txt"));
myBR.close();
Class c = myBR.getClass();
Field in = c.getDeclaredField("in");
in.setAccessible(true);
Object inReader = in.get(myBR);
if(inReader == null){
System.out.println("is closed");
}
else{
System.out.println("is open");
}
If only things that read from BufferedReader and close it are your threads, I would just make synchronized section and set some flat when closing the Reader. So in each thread you should:
Open synchronized section.
Check if stream isn't closed already (check the flag).
Read from stream.
Close stream.
Set the flag.
End synchronized section.
Just be careful and avoid anything that could hang in synchronized section. Basically put there only what is necessary, only read data, process it later.
Related
I want to fetch an HTML page and read in with BufferedReader. So I use try-with-resources to open it handles IOException this way:
try(BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
} catch(IOException e) {
throw e;
}
Is this a good pattern to catch and instantly throw? And what if I omit try at all and state that function throws IOException? If then any potentional memory leak?
Much appreciate any advice!
A catch block is not required in a try-with-resources statement. You could write the following, which would mean exactly the same as your original code:
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream()))) {
// do something
}
So, you can leave out the catch block, if all you ever do there is immediately throw the same exception again.
You do want the try block however, so that the BufferedReader and underlying stream(s) are automatically closed at the end of the block.
Is this a good pattern to catch and instantly throw?
No, catching and immediately re-throwing the same exception does not add anything useful.
To add to #Jesper's excellent answer, you do want to include the try block so that the BufferedReader will be closed right away. If you don't do this, it'll eventually be closed when the object is garbage collected, so it isn't technically a resource leak in the sense that the resources would eventually be reclaimed; however, the "eventually" part is potentially problematic because there are no guarantees as to exactly when that'll happen. Thus, a bigger issue is whether this would create race conditions if it's using a resource that needs to be reused eventually.
I'm not very familiar with the implementation details of that exact class, so this is somewhat speculative, but one example of an issue you can run into with some classes that perform network calls if you fail to return resources to the operating system promptly is port exhaustion.
By way of another example, if you are modifying a file, the file could remain locked until the GC happens to release the file lock by cleaning up the relevant object.
The InputStream is passed as a parameter from somewhere, where it will be further processed and then closed. So I don't want to close the InputStream here. Consider the following code:
void readInputStream(final InputStream inputStream) {
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine() != null) {
// do my thing
}
}
If I close the BufferedReader and/or the InputStreamReader, then the underlying InputStream will be closed as well, according to another Stackoverflow post.
My question: Do Readers need to be closed, even if the underlying InputStream is closed somewhere else? Can I get a memory leak by not closing Readers?
Do readers need to be closed, even if the underlying InputStream is closed somewhere else?
No they absolutely don't need to be in that scenario. But it is generally a good idea to close them anyway.
Can I get a memory leak by not closing readers?
No, there is no memory leak, assuming that the Reader itself becomes unreachable once you have finished with it. And besides, a Reader doesn't typically use a lot of memory.
The more important question is whether you can get a resource leak by not closing a Reader. The answer is ... it depends.
If you can guarantee that the underlying InputStream will always be closed somewhere else in the application, then that takes care of possible memory leaks.
If you can't guarantee that, then there is a risk of a resource leak. The underlying OS level file descriptors are a limited resource in (for example) Linux. If a JVM doesn't close them, they can run out and a certain system calls will start to fail unexpectedly.
But if you do close the Reader then the underlying InputStream will be closed.
Calling close() more than once on a InputStream is harmless, and costs almost nothing.
The only case where you shouldn't close the Reader is when it would be wrong to close the underlying InputStream. For example, if you close a SocketInputStream the rest of the application may not be able to reestablish the network connection. Likewise, the InputStream associated with System.in usually cannot be reopened.
In that case, it is actually safe to allow the Reader you create in your method to be garbage collected. Unlike InputStream, a typical Reader class doesn't override Object::finalize() to close its source of data.
#Pshemo brought up an important point about system design.
If you are accepting an InputStream as an argument, then it may be wrong to wrap it with a local Reader ... especially a BufferedReader. A BufferedReader is liable to read-ahead on the stream. If the stream is going to be used by the caller after your method returns, then any data that has been read into the buffer but not consumed by this method is liable to be lost.
A better idea would be for the caller to pass a Reader. Alternatively, this method should be documented as taking ownership of the InputStream. And in that case, it should always close() it.
Yes, Readers need to be closed. Use a proxy, e.g. CloseShieldInputStream, to prevent the passed parameter from being closed.
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: Similar to the input shield, Apache Commons I/O also provides an output shield to solve the similar problem with closing a wrapping output stream, - CloseShieldOutputStream
For more detailed considerations, please refer to the original answer. Credits to #stephen-c
I have a multi-threaded program, in which I open a BufferedReader to read content from FIFO(named Pipe) file. As I want to implement stream type of solution to read text from FIFO file continuously, I have created a BufferedReader outside of thread task run, and want to keep that open forever as long as application is running.(No close() on bufferedReader)
With the limited(let say 10) threads in ThreadPool will keep look for text in FIFO file and process that text for further. As I am using FIFO it will never reach END OF FILE.
By doing this, For a smaller input file it reads successfully, for a large input file it throws Stream closed IOexception(sporadically). It close automatically, I do not have close() statement.
I have a code in place to acquire and close the semaphore lock at the place where i use br.readLine() to handle race condition issue
java.io.IOException: Stream closed
at java.io.BufferedReader.ensureOpen(BufferedReader.java:122) ~[?:1.8.0_152]
at java.io.BufferedReader.readLine(BufferedReader.java:317) ~[?:1.8.0_152]
at java.io.BufferedReader.readLine(BufferedReader.java:389) ~[?:1.8.0_152]
Question:
For this solution I do not want to close the BufferedReader. What are the consequences?
Can I have a bufferedReader which never be closed? if so what steps I should consider in code.
BufferedReader is not a thread-safe class, so, we can get an uncountable number of various error on attempt to use the same object of that class from different threads.
If I have stream (InputStream or OutputStream) which I did not create but was rather passed to my method as a parameter, should I be closing that stream? Here's an example:
void method(InputStream in) {
try {
//Do something
}
finally {
if(in != null) {
in.close(); //Is this needed and correct?
}
}
Really, "it depends".
As a general rule, you should not close a stream that you didn't have responsibility for opening, but to give a correct answer we would have to understand the context.
It's very possible that the delegation of responsibility requires your method to consume from and close the stream - if this is the case then it should be explicit in the code.
If your method is named readFromStreamAndClose(InputStream in) then the fact that your method closes the stream is very obvious.
In the case that you open the stream yourself, you can always use a try-with-resources block which will close the stream for you - at the same level of abstraction as it was created. In this case - your method (which is called at a lower level than when the stream was opened) should not close the stream.
Generally it is not recommended to close the stream which is not associated to that class.
Following are the reasons,
Streams passed to that method may be used in some other place.
Reusable streams are available in java. If the stream is closed it
cannot be reopened and reused.
In case of Exception when closing the stream you don't know how to
handle that. Because you are dealing with general inputstream and it
may come from any place like File, Network etc.
The class opens the stream is responsible for closing it.
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
No you don't have to do it because it may be used somewhere further in the code.
You do document the method with: "Closes the stream" and change the name method to like readAndClose.
Or create a parameter boolean closeStream and close if true.
Also if the stream doesnt support mark/seek/reset there's no reason to keep it open.
In my Java code, I start a new process, then obtain its input stream to read it:
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
FindBugs reports an error here:
may fail to close stream
Pattern id: OS_OPEN_STREAM, type: OS, category: BAD_PRACTICE
Must I close the InputStream of another process? And what's more, according to its Javadoc, InputStream#close() does nothing. So is this a false positive, or should I really close the input stream of the process when I'm done?
In this case, you want to close() the Reader, which will close its underlying streams. Yes, it's always good practice to close streams, even if at the moment you know the implementation you're looking at doesn't do anything (though, in fact, it does here!). What if that changed later?
FindBugs is only there to warn about possible errors; it can't always know for sure.
Finally yes, your Java process owns the process and Process object you spawned. You most definitely need to close that and the output stream. Nobody else is using them, and, it's important to do such things to avoid OS-related stream funny business.
InputStream is an abstract class - just because its implementation does nothing doesn't mean that the actual type of object returned by process.getInputStream() doesn't.
It's possible that failing to close the input stream in this particular case would do no harm - but I personally wouldn't count on it. Close it like you'd close any other input stream. Aside from anything else, that makes your code more robust in case you ever decide to change it to read from something else - it would be all too easy to (say) read from a file instead, and not notice that you're not closing the FileInputStream.
I think its always a good practice to close all the streams you open. Preferably in the finally{} block. Since it does nothing as java says, why not call the close() method. Its of no harm.