Does InputStreams and OutputStreams in Java close() on destruction? I fully understand that this may be bad form (esp in C and C++ world), but I'm curious.
Also, suppose I have the following code:
private void foo()
{
final string file = "bar.txt";
Properties p = new Properties();
p.load( new FileInputStream(file) );
//...
}
Does the nameless FileInputStream goes out of scope after p.load(), and therefore get destroyed, kinda like C++ scoping rules? I tried searching for anonymous variable scope for java on Google, but that didn't turn up what I thought it would be.
Thanks.
First answer: there's no such thing as "destruction" (in the C++ sense) in Java. There's only the Garbage Collector, which may or may not wake up and do its job when it sees an object that's ready to be collected. GC in Java is generally untrustworthy.
Second answer: sometimes yes, sometimes no, but not worth taking a risk over. From Elliote Rusty Harold's Java IO:
According to Harold, the same goes for Input or Output streams. There are some exceptions (he notes System.in), but in general, you're taking a risk if you don't close file streams when you're done. And close them in a finally block, to make sure they get closed even if an exception is thrown.
No, there are no destructors in Java. There may be other references to the object, even after one particular reference to it goes out of scope (or is modified). If the object is no longer reachable, the stream may have its finaliser called sometime later which will close the stream.
Edit:Properties.load
is peculiar in the it closes the stream passed to it.Properties.loadFromXML
is the special method I appear to have been thinking about five or so years ago. (API doc should probably say before rather than after.) Thank you @tzimnoch.The short answer is "maybe, but don't bet on it!".
Somewhere in the stack of classes that implement FileInputStream is a class that has a
finalizer
that will effectively close the stream (and release the resource) when it is run.The problem is that there is no guarantee that the finalizer will ever run. Quoting from the JLS (section 12.6):
This makes stream finalization problematic:
The variable goes out of scope and is therefore destroyed. But in Java, there is a very big distinction between a variable and the object which the variable points to.
The object pointed to is not destroyed merely when the variable goes out of scope. The object is only destroyed when the Java runtime engine decides it feels like getting around to destroying objects that are not pointed to by any in-scope variables.
I used to assume streams would be closed automatically eventually via garbage collection, but anecdotal evidence indicates that failure to manually close them results in a resource leak. You will want to do something like this instead:
closeQuietly()
is a method onIOUtils
in Apache's commons-io library.