> -----Original Message-----
> From: David Holmes [mailto:email@example.com]
> Well I was just considering a use of a finalizer that involved freeing
> a native memory block. It would be really bad if the finalizer could
> run before the method that will use the native memory. ;-) It would
> also be really ugly to have to use synchronization just in case the VM
> uses a separate finalizer thread.
AFAIK, all correct VMs use at least one separate finalizer thread, so you should definitely consider that case.
Finalizers must be run in a thread not holding user visible locks. The only easy way to get such a thread is to start one for that purpose. It's popular to ignore this requirement in version 1 JVMs. But most large applications deadlock or crash when you do that, so it tends to get fixed in version 2.
> Hmmm. I suppose if we just said "an object is always reachable while
> an invocation upon it is active" then the compiler folk would get
I suspect that would be a significant compiler change. And there are interesting interactions with the rest of the memory model. (Is the end of an invocation ordered with respect to other memory accesses?) It would also make tail call elimination impossible in some simple cases. (A call frame may have to be preserved simply to preserve the "this" pointer for the frame.) The nice thing about relying on synchronization is that nearly all JVMs (possibly all) already do the right thing.
I could see adding a separate construct to ensure reachability of a reference up to a certain point, as Jerry suggests. But that significantly complicates both the programming model and the spec. Given that finalization should be rare, I'm not sure whether the performance cost matters enough. If it turns out it does, it still seems to me that (a) synchronization should keep the object reachable anyway, since synchronization is often needed for other reasons, so this change/clarification wouldn't hurt, and (b) it's relatively easy to add such a construct later.
Right now the perception seems to be that finalization is too complicated and essentially unusable. If synchronization kept objects reachable, there would be a reasonably simple and consistent rules for its use. The relevant one is simply:
Finalization introduces concurrency, since finalizers are usually run in a separate thread. Finalizable objects should thus use synchronized methods to access shared data, including object fields referenced by the finalizer.
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:43 EDT