RE: JavaMemoryModel: A problematical case for finalizers

From: Boehm, Hans (hans_boehm@hp.com)
Date: Wed Apr 09 2003 - 14:44:07 EDT


It looks to me like this discussion is going around in circles. I thought we basically agreed that we need to require that synchronized(x) ... ensures that x is reachable at some point at which the lock is held. The arguments for this are:

1) Without it all existing code involving finalizers is broken.
2) AFAIK, it is already satisfied by existing implementations.
3) I don't think it has any significant impact on potential future optimizations.
4) None of the other proposals replace it. (System.keepLive() could be used instead, and should perhaps be used in some performance-critical code. But even if we adopt that, I think full synchronization should also work. It's far easier to explain. And it's cheaper if you need to synchronize anyway.)
5) Most people, even on this list, seem to be surprised that this isn't already the case.

Assuming we deal with finalization issues at all, why would we not want to require this? (And I now think we have to deal with these issues, since they interact too much with other parts of the proposal.)

If we do add System.keepLive(), I would first require that a write a volatile field makes an object reachable (which makes sense to me anyway), and then explain the semantics in terms of a hidden volatile field, as Bill did.

Hans

> -----Original Message-----
> From: Jerry Schwarz [mailto:jerry.schwarz@oracle.com]
> Sent: Wednesday, April 09, 2003 9:25 AM
> To: Bill Pugh; javamemorymodel@cs.umd.edu
> Subject: Re: JavaMemoryModel: A problematical case for finalizers
>
>
>
>
> Bill writes
>
>
> >Note that declaring the send and finalize methods as
> synchronized with fix
> >the problem.
>
>
> I believe it does not.
>
> A. The lock might not part of the object. It might, for
> example, be pointed
> to by the object. The code would then only need to hold a
> pointer to the
> lock, not to the object itself. This would be plausible if
> there was some
> hardware synchronization operations that only worked on a
> specific area of
> memory. (I have no idea if there is any such hardware.)
>
>
> B. Consider the code
>
> Foo f = new Foo(...);
> f.send(...);
> f = null;
>
> In this case the compiler can determine that f is never
> accessible from
> another thread and therefore it doesn't have to actually perform the
> lock/unlock and so it doesn't need to hold onto the pointer
> to f. (It still
> needs to do memory barriers as appropriate, but those do not
> always require
> use of the pointer to f).
>
>
> > So would a call to System.keepAlive(this) at the end of
> the send method,
> > if people are interested in that.
>
>
> This is the only way. And this will work only if the semantics of
> System.keepAlive specifically require that it do so. Merely
> giving the
> semantics in terms of operations on a hidden volatile doesn't
> do the job
> because it is possible (indeed we expect) that the compiler
> will optimize
> away the actual operations on the volatile.
>
> At 07:43 AM 4/9/2003, Bill Pugh wrote:
> >In talking about finalizers with Doug Lea, I mentioned a
> scenario which I
> >thought everyone knew about but Doug hadn't considered. He
> suggested I share it
> >with everyone.
> >
> >Consider
> >
> >public class Foo {
> > OutputStream out;
> >
> > public Foo(...) {
> > out = ...;
> > }
> >
> > public void send(...) {
> > byte [] buf = ...;
> > out.write(buf);
>
> > }
> > protected void finalize() {
> > out.close();
> > }
> > }
> >
> >Now consider the code:
> >
> > { Foo f = new Foo(...);
> > f.send(...);
> > }
> >
> >Now within the code for send, a VM might try to optimize the call to
> >out.write into a tail call to out.write.
> >
> >The VM could also inline the call to send.
> >
> >In this situation, there wouldn't be any live reference to
> the Foo object
> >from the stack during the call to write. However, the write
> method could
> >take a very long time to execute if it is pushing a large
> amount of data
> >down a narrow pipe. So the Foo object could be finalized,
> and the output
> >stream be closed, while the output stream is still being written to.
> >
> >Are we happy to declare such code broken?
> >
> >Note that declaring the send and finalize methods as
> synchronized with fix
> >the problem. So would a call to System.keepAlive(this) at
> the end of the
> >send method, if people are interested in that.
> >
> > Bill
> >-------------------------------
> >JavaMemoryModel mailing list -
http://www.cs.umd.edu/~pugh/java/memoryModel

-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel



This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:44 EDT