28 Mar 97 12:33:39 -0800
I'd like to add my 2cents on these topics:
1) Java's finalization
2) Is finalization necessary
3) Collection of scarce resources
4) Latency of finalization execution
5) Finalization idioms
1. A language spec shouldn't provide too tight a specification of when finalizers are run.
Now, if the Java spec spec says that finalizers don't ever have to be run, that would be
stupid. In any case, I'm sure that in time market forces will guide Java implementations
to do the right thing. Any JVM which breaks programs that run on other JVM's will lose
2. I'm really surprised that anyone who believes the GC's are a "good thing" would argue
that using it to release non memory resources is a "bad thing". Memory is just a particular
type of resource. We garbage collect because it's too damn hard to explicitly release
resources; memory or other. It is hard for a particular static location in a piece of code
to know whether some other dynamic piece of the program holds a reference to an object.
Explicitly releasing a resource when another reference to the resource exists would
cause a disaster. It doesn't matter if the resource is memory or a file, a window, or
3) Using GC to release scarce resources can be dealt with. Either by virtualizing the
resource, or by explicitely calling the GC if you can't obtain a resource. I prefer
virtualizing the resource since that keeps client code cleaner.
4) Timeliness of finalization. I haven't heard a reason for why finalizers must run within
a small window of time after the last reference to them is dropped. Perhaps I missed it. The
arguments I have heard describe the scarcity problem: you must finalize quickly to
release a scarce resource. Are there any other latency issues?
5) Using GC to reclaim resources results in using different coding idioms. One is
virtualizing scarce resources which I described in my previous message. Another is
separating local from global finalization. This can be used to handle many cases:
- Window. Local:close window. Global: destroy window.
- File. Local: flush buffers. Global: close file.
- Semaphore. Local: decrement semaphore count. Global: destroy semaphore.
- Socket. Local: flush buffers. Global: close connection.
Consider the window case which one poster mentioned. As another poster noted, closing a
window is locally decideable, while destroying it requires global knowledge.
Therefore, a piece of code can close the window whenever it chooses, but it must rely on the
finalizer to destroy the window. When the user presses the close button, the event
handler knows it can close the window. The event handler does not know if the window is
reachable from anywhere else. Consider a dialog box. When it is closed, it shouldn't be
destroyed. Some other piece of code may need to read the values from its fields.