I brought this up previously, and the discussion didn't go very far. After
thinking about it some more, I'm convinced that this is a serious problem.
Say we have:
class A {
OutputStream x = new FileOutputStream("log");
InputStream y;
static int z;
protected void finalize() { ... }
}
A a = new A();
a.y = new FileInputStream("test");
A.z = 69;
a = null;
As written, when the finalize method is invoked, which writes, if any, is
the finalizer guaranteed to see?
x1) The write to the x field (in the constructor)
x2) The writes that construct the FileOutputStream which is assigned to x
y1) The write to the y field (after construction)
y2) The writes that construct the FileIntputStream which is assigned to y
z) The write to the static field (after the last live reference to a)
The problem is that losing the last reference to an object is a
asynchronous signal to another thread to run the finalizer. Since the
moment at which the last reference to an object is lost is so hazy, it
makes it hard for the VM to make any guarantees.
Rather than dictate a particular solution, I'd just like others to think
about what solutions are possible, and the implications for VM implementers
and for people trying to use finalizers.
A number of people have argued that the whole concept of finalizers is
broken, and perhaps this is more evidence of that. Unfortunately, we
probably can't just deprecate finalizers. If we tried to convince people
that they had to use synchronization just because they had a finalizer, we
would have a tough education campaign ahead of us.
As was mentioned previously, many of these issues also arise for weak
references. But I think the cases involving finializers are going to be
the most difficult ones to solve, so we should start by figuring out the
feature set we want for finalizers.
Bill
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:24 EDT