On Wed, 18 Jun 2008, Lew wrote:
> Lew wrote:
>>>> Joshua Bloch, /Effective Java/
>>>> <http://java.sun.com/docs/books/effective/index.html>,
>>>> Item 7, "Avoid finalizers".
>
> Tom Anderson wrote:
>> And Lew, this is especially for you:
>>
>> http://weblogs.java.net/blog/tball/a...ly_a_good.html
>>
>> The evils of finalizers, AND error logging!
>
> That article suggests heavy use of finalizers,
I wouldn't say 'heavy' - just in places where cleanup absolutely has to be
done. I don't think there are many places like that in an application.
Bear in mind that the alternative to using finalizers for this is to risk
the cleanup not being done, which is incorrect behaviour.
> Lew:
>>> They are not guaranteed to run at all.
>
> Tom:
>> Isn't the only situation where they won't run at all if the program exits?
>
> Not in principle, no. If there isn't enough pressure on memory to
> force a collection after the Java object is dereferenced, then
> 'finalize()' will not happen.
>
> OK, yes, because then by definition the program will exit without
> running 'finalize()'.
Gotcha!
I guess there's no useful difference between 'never' and 'not for an
arbitrarily long time', so i take your point.
> Even if it does eventually run, it may have been delayed long enough to
> put pressure on other resources. For example, if 'finalize()' releases
> a resource connection, it may take so long to get around to 'finalize()'
> that the program runs out of available connections.
That's a good point. But this is a reason not to use finalizers as a
general cleanup mechanism, but not a reason not to use them as a backup -
in fact, quite the opposite. If you didn't have the finalizers, and the
code was failing to close all connections properly, you'd run out of
connections with no ability to do anything about it. If the finalizers are
there, the connections will be closed provided that finalization runs.
What alternatives are there? The only one i can think of is using a
timeout, so that if a connection has been idle for a certain length of
time, it gets released. This has the advantage of guaranteeing that
resources will be released within a certain amount of time, but suffers
from the disadvantage of potentially releasing resources while they're
still in use.
Ideally, the code handling the interaction with the resource would hold on
to enough lightweight state to be able to transparently reopen the
connection if it was needed again, so the calling code never got a
SorryIThoughtYouUsingThatAndGotRidOfItException. I once worked on a CORBA
implementation that did this - it had a 'smart reconnect' feature whereby
if the socket was closed, for instance by an error, there was enough
information in the object references to reopen it. In fact, it went one
better, and stashed information from the CosNaming or CosTrading lookup
originally used to find the object, so if the server hosting the object
actually went away, it could find you a substitute object from somewhere
else!
tom
--
forget everything from school - you are programmer