Re: Closing ByteArrayOutputStreams
- From: "Chris Uppal" <chris.uppal@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Tue, 9 May 2006 10:47:32 +0100
Scott Harper wrote:
First, if I have a locally declared stream (any stream) inside a method,
when the method returns and the stream object goes out of scope, wouldn't
it automatically be cleaned up, closed, and returned to the system? I
think of this the way other objects behave, and when their reference
counts go to zero, they are garbage collected. However, one colleague is
of the opinion that this is not the case, and that I have to close the
stream before it can be finalized and handed over to the garbage
collector.
Your colleague is technically wrong; if the stream is cleaned up by
finalisation at all, then it will be cleaned up whether or not you have called
close() explicitly. However, the general point is good -- you should not rely
on finalisation if you can possibly avoid it.
BTW, there are some cases where it is appropriate /not/ to close a stream. For
instance, if you have a decorator stream (such a BufferedOutputStream) wrapped
around a FileStream, and you want to stop using buffering without closing the
underlying file, then you would flush() the BufferedOutputStream, and then
discard the reference to it without close()ing that stream. Needless to say,
you should explicitly close() the underlying FileStream when you have finished
with it.
In this case, I am dealing primarily with ByteArrayOutputStreams, and it
seems counter-intuitive that they are consuming a lot of system resources
anyway. A little more digging into the API spec shows that
ByteArrayOutputStream is a bit of an oddity. And there is also a mistake in
the design which makes this more awkward that it should be.
If your code doesn't "know" that it is writing to a ByteArrayOutputStream (e.g.
you have utility code which could be creating a byte[] array or writing to a
file, or to the network -- and it doesn't care which), then clearly that code
should close() the stream (if it close()es it at all) no matter where the
stream is really writing to. If that is the case, then just don't worry about
close() not doing anything -- it's doing everything it /should/ do, and your
code will work correctly no matter what kind of stream you use.
OTOH, your code might "know" that it /is/ using a ByteArrayOutputStream.
That's quite possible too. In that case you should have the choice between two
sensible ways of coding the "unnecessary" clean-up, but Sun have messed up the
API. You can just say, well we don't need to close() this stream, so I won't
bother. A perfectly legitimate choice, and what I'd probably do myself.
Alternatively, you might want to future-proof your code a little, and close()
the stream explicitly, even though it's unnecessary, as a bit of insurance in
case you ever make that code more general. (Or maybe in response to company
coding standards, or because some automated code checking tool complains.)
That's a legitimate choice too, but Sun have unfortunately declared
ByteArrayOutputStream.close() to throw IOException even though it doesn't do
so. That error[*] means that even though your current code may know that it is
using a ByteArrayOutputStream (i.e. the stream variable is declared with that
specific type rather than a more general one), it is /still/ necessary to add
code to handle an exception which cannot be thrown.
([*] And I believe it /is/ an error. A bit of mis-design, possibly caused by a
historical copy-and-paste mistake.)
So, I think that how you should handle this depends on how your code is
designed. If it is really /necessary/ that the variable in question holds a
ref to a ByteArrayOutputStream, then I wouldn't bother closing it at all.
Otherwise I wouldn't declare it with a more general type than
ByteArrayOutputStream and would close() it properly and would include proper
handling for the exception.
Oh, another option would be to create a trivial subclass of
ByteArrayOutputStream which overrode close() and guaranteed (to the compiler)
that it wouldn't throw anything.
-- chris
.
- References:
- Closing ByteArrayOutputStreams
- From: Scott Harper
- Closing ByteArrayOutputStreams
- Prev by Date: Re: Where do the Java imports exist?
- Next by Date: Re: HashMap<Object, Double> returns what instead of null?
- Previous by thread: Re: Closing ByteArrayOutputStreams
- Next by thread: Generics and reflection
- Index(es):
Relevant Pages
|