Re: Closing ByteArrayOutputStreams



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



.



Relevant Pages

  • Re: Closing ByteArrayOutputStreams
    ... that "A program should close a stream as soon as it ... the streams are eligible for garbage collection. ... "Closing a ByteArrayOutputStream has no effect. ... What this means is that the 'close' method on the OutputStream class itself ...
    (comp.lang.java.programmer)
  • Closing ByteArrayOutputStreams
    ... I've read in a couple places (the Essential Java Classes trail of the Sun Java ... that "A program should close a stream as soon as it is ... "Closing a ByteArrayOutputStream has no effect. ... I suspect that an ancestor of OutputStream ...
    (comp.lang.java.programmer)
  • Re: Net threads and Windows OS file system
    ... Stream object doesn't help you access the Stream object in a thread-safe ... Stream.Synchronizedreturns a reference to different wrapper? ... As you note, it simply uses the Stream reference passed to it, and so all wrappers do use the same synchronization object. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Load an object from a file
    ... I do not know how to get the needed stream from a given file name. ... package jvm is ... I have tried to represent a java class file format ...
    (comp.lang.ada)
  • Re: Load an object from a file
    ... In my Ada self-study context, I was asking myself how can I create and ... Stream: not null access Ada.Streams.Root_Stream_Type'Class) ... and deallocation by nesting declare blocks, ...
    (comp.lang.ada)