Re: finalize() overhead
On Nov 7, 7:10 pm, Joe Seigh <jseigh...@xemaps.com> wrote:
Eric Sosman wrote:
Joe Seigh wrote:
I guess overriding finalize() isn't recommended too much because
of it's adverse effect on GC performance. But I assume that
if it's used a lot. You need finalize() for things like guaranteeing
proper clean up of non-memory resources like file descriptors and
db connections. One way anyway.
So this sort of use of finalize is considered acceptable? Or should
it be avoided at all costs even if you leak file descriptors or
whatnot?
Can't remember who said it (Bloch? Eckel? not sure), but
the thing to keep in mind is that finalize() is a creature of
the garbage collector, the garbage collector's concern is
memory and memory only, so finalize() should be about memory
and memory only. Eckel (I'm sure, this time) also suggests
a debugging role: If an object becomes garbage without its
close() or dispose() or disconnect() method being called, a
finalize() can emit a warning message to that effect.
If you need to get rid of file handles, database connections,
windows, sessions, sockets, locks on the frammis interface, or
other non-memory kinds of things, you should provide a close()
or dispose() or terminate() or ahhScrewItAll() method to shut
down, release, relinquish, or otherwise sever your association
with such entities. The finalize() method is *not* the right
vehicle for such things; finalize() is *not* a "destructor."
The key word here is guarantee. Obviously the proper way is to
use a close method but the mere existence of such a method doesn't
guarantee its proper use.
Neither does finalize().
The JVM is free to put off the collection of any given object for as
long as it wants, and to finalize objects in any order it feels like.
Objects that have not been collected when the program ends are likely
never to be finalized. This is an intrinsic feature of Java's
finalization and can't be "worked around"; even the
runFinalizersAtExit method doesn't guarantee that finalizers will ever
be run (trivially, if the JVM dies of a KILL signal, it never gets a
chance to finalize anything, but there are other ways to cause it with
Sun's JVM).
Since Java has neither destructors nor C#'s using statement and
IDisposable interface, the idiom for using and discarding resources in
a controlled, guaranteed way is similar to this:
InputStream source = new FileInputStream ("foo.dat");
// do not put code here, ever.
try {
readDataFrom (source);
} finally {
source.close ();
}
Using finally like this does guarantee that, regardless of whether or
not the code represented by readDataFrom succeeds, the source stream
will be closed. The same pattern works for any releaseable resources:
explicit locks, database connections, and so on. It's a construct
that should be familiar to any Java programmer, and while it's a
little verbose, it works rather well and gives the programmer complete
control over the lifecycle of the resource.