[Python-Dev] finalization again

Guido van Rossum guido@python.org
Tue, 07 Mar 2000 19:50:38 -0500


> [Guido]
> > Tim tells Guido again that he finds the Java rules bad, slinging some
> > mud at Guy Steele, but without explaining what the problem with them
> > is ...
> 
> Slinging mud?  Let's back off here.  You've read the Java spec and were
> impressed.  That's fine -- it is impressive <wink>.  But go on from
> there and see where it leads in practice.  That Java's GC model did a
> masterful job but includes a finalization model users dislike is really
> just conventional wisdom in the Java world.  My sketch of Guy Steele's
> involvement was an attempt to explain why both halves of that are valid.

Granted.  I can read Java code and sometimes I write some, but I'm not
a Java programmer by any measure, and I wasn't aware that finalize()
has a general bad rep.

> I didn't think "explaining the problem" was necessary, as it's been
> covered in depth multiple times in c.l.py threads, by Java programmers
> as well as by me.  Searching the web for articles about this turns up
> many; the first one I hit is typical:
> 
>     http://www.quoininc.com/quoininc/Design_Java0197.html
> 
> eventually concludes
> 
>     Consequently we recommend that [Java] programmers support but do
>     not rely on finalization. That is, place all finalization semantics
>     in finalize() methods, but call those methods explicitly and in the
>     order required.  The points below provide more detail.
> 
> That's par for the Java course:  advice to write finalizers to survive
> being called multiple times, call them explicitly, and do all you can
> to ensure that the "by magic" call is a nop.

It seems the authors make one big mistake: they recommend to call
finalize() explicitly.  This may be par for the Java course: the
quality of the materials is often poor, and that has to be taken into
account when certain features have gotten a bad rep.  (These authors
also go on at length about the problems of GC in a real-time situation
-- attempts to use Java in sutations for which it is inappropriate are
also par for the cours, inspired by all the hype.)

Note that e.g. Bruce Eckel in "Thinking in Java" makes it clear that
you should never call finalize() explicitly (except that you should
always call super.fuinalize() in your finalize() method).  (Bruce goes
on at length explaining that there aren't a lot of things you should
use finalize() for -- except to observe the garbage collector. :-)

> The lack of ordering
> rules in the language forces people to "do it by hand" (as the Java
> spec acknowledges: "It is straightforward to implement a Java class
> that will cause a set of finalizer-like methods to be invoked in a
> specified order for a set of objects when all the objects become
> unreachable. Defining such a class is left as an exercise for the
> reader."  But from what I've seen, that exercise is beyond the
> imagination of most Java programmers!  The perceived need for ordering
> is not.).

True, but note that Python won't have the ordering problem, at least
not as long as we stick to reference counting as the primary means of
GC.  The ordering problem in Python will only happen when there are
cycles, and there you really can't blame the poor GC design!

> It's fine that you want to restrict finalizers to "simple" cases; it's
> not so fine if the language can't ensure that simple cases are the only
> ones the user can write, & can neither detect & complain at runtime
> about cases it didn't intend to support.  The Java spec is unhelpful
> here too:
> 
>    Therefore, we recommend that the design of finalize methods be kept
>    simple and that they be programmed defensively, so that they will
>    work in all cases.
> 
> Mom and apple pie, but what does it mean, exactly?  The spec realizes
> that you're going to be tempted to try things that won't work, but
> can't really explain what those are in terms simpler than the full set
> of implementation consequences.  As a result, users hate it -- but
> don't take my word for that!  If you look & don't find that Java's
> finalization rules are widely viewed as "a problem to be wormed around"
> by serious Java programmers, fine -- then you've got a much better
> search engine than mine <wink>.

Hm.  Of course programmers hate finalizers.  They hate GC as well.
But they hate even more not to have it (witness the relentless
complaints about Python's "lack of GC" -- and Java's GC is often
touted as one of the reasons for its superiority over C++).

I think this stuff is just hard!  (Otherwise why would we be here
having this argument?)

> As for why I claim following topsort rules is very likely to work out
> better, they follow from the nature of the problem, and can be
> explained as such, independent of implementation details.  See the
> Boehm reference for more about topsort.

Maybe we have a disconnect?  We *are* using topsort -- for
non-cyclical data structures.  Reference counting ensure that.
Nothing in my design changes that.  The issue at hand is what to do
with *cyclical* data structures, where topsort doesn't help.  Boehm,
on http://www.hpl.hp.com/personal/Hans_Boehm/gc/finalization.html,
says: "Cycles involving one or more finalizable objects are never
finalized."

The question remains, what to do with trash cycles?  I find having a
separate __cleanup__ protocol cumbersome.  I think that the "finalizer
only called once by magic" rule is reasonable.  I believe that the
ordering problems will be much less than in Java, because we use
topsort whenever we can.

--Guido van Rossum (home page: http://www.python.org/~guido/)