[concurrency-interest] [Javamemorymodel-discussion] Fences.keepAlive

Boehm, Hans hans.boehm at hp.com
Tue Jan 20 16:29:29 EST 2009


> From: Alexander Terekhov [mailto:alexander.terekhov at gmail.com] 
> 
> On Tue, Jan 20, 2009 at 8:20 PM, Boehm, Hans 
> <hans.boehm at hp.com> wrote:
> > I'd be inclined to somewhat simplify the example, and not use the 
> > constructor.  I'm also not sure I'd mention the word 
> "native", since 
> > that seems to mislead people to believe that this is a native code 
> > issue.  Something like:
> >
> > * class Resource {
> > *   static Resource[] externalResourceArray = ...
> > *   int myIndex;
> > *   Resource(...) {
> > *     myIndex = ...
> > *     externalResourceArray[myIndex] = ...;
> > *     ...
> > *   }
> > *   protected void finalize() {
> > *     externalResourceArray[myIndex] = null;
> > *     ...
> > *   }
> > *   void foo() {  // This might be the last use of this object.
> > *      int i = myIndex;
> > *      //  Without keepAlive, this object could be finalized
> > *      //  here, and externalResoureArray[i] could be
> > *      //  cleared, since the object itself may not otherwise
> > *      //  be needed; if there are no later accesses, only
> > *      //  the index i is still live.
> > *      bar(externalResourceArray[i]);
> > *      keepAlive(this);
> > *   }
> > * }
> 
> Q: What does it mean to have no GC?
> A: You must write "delete" (C++ locals aside for a moment) at 
> destruction point(s).
> 
> Q: What does it mean to have a GC?
> A: You must write "keepAlive" in every member function 
> possibly affected by the GC's premature destruction of *this.
> 
The latter of course only applies to finalizable objects, of which there should be very few.

The real difference between say, the C++ and Java approaches here is actually not so much the presence of GC.  C++ shared_ptr fundamentally has the same issues, in some ways more so.  It seems to me that interestingly the difference is that C++ effectively went for simpler semantics and less performance here, while Java went for more performance at the expense of programmability.  C++ delays destruction of locals until the end of the block, thus prohibiting dead variable elimination where it might be visible.  Hence a shared_ptr and the like can't be destroyed early.  Java allows pointers to disappear early in ways that are visible to finalizers.  This makes at least some small amount of sense, since C++ destructors are intended to be much more common that Java finalizers, and the performance impact would still be more or less universal in Java.  Whether it is really the right decision for Java, I don't know.  But I think the decision was effectively (probably unintentionally?) made around the Java 1.1 time frame, and changing it is likely to be nontrivial.

Hans


More information about the Concurrency-interest mailing list