Reputation: 606
I'm trying to use a FileOutputStream anonymously for storing a property with java.util.Property's store method.
Properties p = new Properties();
. . .
p.store(new FileOutputStream("nameOfFile"), "Created by me.");
Reading the javadocs for the store method it says that the stream will be flushed and remain open after the method returns.
I'm wondering what happens with the stream. Since I've instantiated it anonymously I'm under the assumption that the object will be garbage collected immediately (if that is wrong, please correct me). However, I was taught to always close my streams when I'm finished with them. In this case, I am unable to close the stream since I have no object referring to it. Do I need to be worried about the stream being left open here, or does Java take care of it appropriately in this case by immediately collecting the object?
Upvotes: 4
Views: 970
Reputation: 72884
Garbage collection generally does not include resources like open files or streams, unless the finalize
method explicitly closes the underlying resources of the object.
Checking the code of finalize
for FileOutputStream
, it seems to make sure the close
is called:
/**
* Cleans up the connection to the file, and ensures that the
* <code>close</code> method of this file output stream is
* called when there are no more references to this stream.
*
* @exception IOException if an I/O error occurs.
* @see java.io.FileInputStream#close()
*/
protected void finalize() throws IOException {
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
} else {
/*
* Finalizer should not release the FileDescriptor if another
* stream is still using it. If the user directly invokes
* close() then the FileDescriptor is also released.
*/
runningFinalize.set(Boolean.TRUE);
try {
close();
} finally {
runningFinalize.set(Boolean.FALSE);
}
}
}
}
However, it's always better to always close the resource manually, or in a try-with-resources
statement, because not all stream objects may close upon being de-referenced, and even if they do finalization is not guaranteed to occur according to expectations:
try(FileOutputStream outStream = new FileOutputStream("nameOfFile")) {
Properties p = new Properties();
. . .
p.store(outStream, "Created by me.");
}
Upvotes: 2
Reputation: 19171
That's not an anonymous object (or rather an anonymous class). It's just an unassigned object instantiation.
Once you create it and pass it to store
there is a reference to it, therefore it is not GC'd. Once store
returns that reference disappears, but you should still track the variable and dispose of it after store
returns. It is safer to just to treat all resources in the same standard way and call close
when you are done with them, this helps avoid a lot of resource leak errors when some finalize
methods call close
ad other's don't, and also avoids issues due to non-deterministic GC.
You also don't know what may change in a finalizer implementation in a future version so always calling close
is best practice.
A try-with-resources block (Java Tutorials > The try-with-resources statement) is ideal for this:
Properties p = new Properties();
try (FileOutputStream stm = new FileOutputStream("nameOfFile"))
{
p.store(stm, "Created by me.");
} catch (IOException e) {
// TODO: handle this
}
That block, when used with any (and potentially multiple) Autocloseable
, will call close
at the end and nicely handle things like exceptions on close
or exceptions in the body and on close
as well. If both the body and close
throw exceptions then the body exception is rethrown and the close
exception is available through e.getSuppressed()
.
You should not call Autocloseable.close()
yourself if you use one of these blocks as that method is not indempotent - calling it twice may have side effects the second time. If you have a Closeable
then you are safe to call it multiple times. From the docs:
Note that unlike the close method of Closeable, this close method is not required to be idempotent
In Java 6 or less you have to do your own exception handling statement which is hard as you have to handle the case where both your body, and the close
both throw exceptions.
Upvotes: 4
Reputation: 1251
Create an object...
FileOutputStream fos = new FileOutputStream("nameOfFile")
And then use it...
p.store(fos, "Created by me.");
Close it on finally.
The Properties.store() command does not keep a reference to the stream hence there are no references to it and hence it will be GC'ed after the method returns as that is the extent of the streams scope.
Upvotes: 0