Re[2]: [gclist] Finalization and object orientation.

David Chase chase@world.std.com
Fri, 28 Mar 1997 14:39:02 -0500


>At 07:59 PM 3/27/97, Colvin, Greg wrote:
>>File handles seem to be the kind of resource that a finalizer 
>>is handy for: they have no owner but the process, they are 
>>easily encapsulated in a class, and it can be hard to know 
>>statically when the last user of file is gone.

At 08:50 PM 3/27/97 -0800, Scott Meyer wrote:
>I'd point out that in at least one window system, X, a
>file handle is associated with a window or set of windows.
>Sometimes open file handles are associated with entities
>which are visible to the outside world, sometimes not.

Possibly so.  In the case of X, this may have just been
a bone-headed design decision (wouldn't be the first one,
not like I'd ever miss a chance to say bad things about
XWindows).  Sun's NeWS/X11 server copied this model, and
actually relied on "garbage collection" to take down the
window in a timely fashion.  This meant that "garbage
collection" was really reference counting, and freeing
and recursive dereferencing was not lazy.  A friend of
mine was working on the interpreter, and we investigated
the possibility of getting rid of reference counting, and
it just could not be done.

>The key issue is latency, the delta between the time when the
>opened file object becomes garbage and the time when the
>finalizer is run (and closes it).  To the extent that file
>handles are not attached to things that the outside world
>cares about, treating them as just another sort of "memory"
>and firing off a gc when you run out of them is fine.  Conversely,
>if you actually care about latency, finalization is not
>the ticket (though you might want it around to keep things from
>crashing).

Note that latency can matter because the resource is user-visible,
or latency can matter because a resource is scarce.  For whatever
reason, file handles are often scarce (probably because there's no
garbage collection in the underlying OS).  Failure to obtain a
resource could trigger a garbage collection in hopes of forcing
some finalization to occur, but then you've added a weird latency
to resource acquisition.

>Dragging this all back to the original point about OO and
>encapsulation, if you care about latency then you need to
>deal with latency inside the encapsulation you provide.
>Finalization (however well specified) won't do it for you.

That's not 100% true.  If you look at the Java model of finalization
carefully, I think it is designed to allow the implementation of
relatively timely finalization, once an object is only finalizer-
reachable.  A consequence of this is that there are finalizers
that are "legal" in the letter-of-the-law sense, but are otherwise
ill-advised.

Designing a collector that will also detect garbage quickly is
another matter.

> The assumption that the post finalized version of an object must be
> less useful is a bogus one inherited from C++ which smashes the vtable
> pointer. The post finalized version could contain added value.

This is hardly a bogus assumption, and it is not solely a result
of C++ quirks (though it is reasonable to make the default assumption
that anything inherited from C++ is bogus).  In my view of the world,
if anything referred to by a finalized object may or may not be in
some weird state (because it, too, was finalized) then it is difficult
to regard that object as having "added value".  (If you disagree with
this assumption of mine, then the rest of my argument makes little
sense, but I will continue).  So, in order to ensure that things
referenced by a finalizer have not yet been finalized, the finalizer
ordering problem reappears.  The question of what to do about finalizable
cycles reappears (rare in Cedar, people at Xerox assert, but unclear
whether that will be true in Java, where every object inherits a finalizer,
though the default is trivial).  To run finalizes in order and avoid
finalizing a resurrected object, the garbage collector either finalizes
very slowly, or employs write-barriers to detect resurrection.  Given
the costs of the generality that you advocate, I find that I am very
comfortable with Java's more limited approach to finalization.

David