Reputation: 147
I was just going through the implementation of FileInputStream and confused with the close method implementation, which is as given below,
public void close() throws IOException {
synchronized (closeLock) {
if (closed) {
return;
}
closed = true;
}
if (channel != null) {
channel.close();
}
fd.closeAll(new Closeable() {
public void More ...close() throws IOException {
close0();
}
});
}
This internally calls closeAll
on FileDescriptor, which releases all the Closables (not only the particular instance which calls the close). So a close call on an Input Stream closes all the streams share that FileDescriptor.
FileInputStream is = new FileInputStream("Some file");
BufferedInputStream br = new BufferedInputStream(is);
FileDescriptor fd = is.getFD();
FileInputStream is1 = new FileInputStream(fd);
BufferedInputStream br1 = new BufferedInputStream(is1);
is.close();
System.out.println(is1.read());
In the above example FileDescriptor
fd
is shared among streams is
and is1
. A close call on is
closes is1
as well (basically fd
is closed/released)
My question is, FileInputStream has a flag to indicated its closed or not, but still why its closing the FileDescriptor when other active streams are pointing to it, making all of them fail/invalid, instead of just closing the calling instance and close the FileDescriptor when no other streams are pointing to it?
Upvotes: 3
Views: 2035
Reputation: 5423
If you open FileInputStreams
from a File
object instead of a FileDescriptor
you'll get the behavior you expect:
File f = new File( ... );
InputStream in1 = new FileInputStream( f );
InputStream in2 = new FileInputStream( f );
You'll see in the FileInputStream( File ) constructor source that this creates a new FileDescriptor
for each FileInputStream
instead of sharing one passed in, as happens in the FileInputStream( FileDescriptor ) constructor.
From the javadoc, FileDescriptor wraps the underlying native OS structure representing an open file handle.
The whole purpose of InputStream.close()
is to clean up those native resources. So if two InputStreams are sharing the native file handle, when one gets closed the other is going to be affected as well.
In the alternative example that I provided above, two independent file handles are created at the OS / native level, so they can be closed independently.
Upvotes: 1