Re: JavaMemoryModel: init methods

From: Doug Lea (dl@cs.oswego.edu)
Date: Tue Sep 26 2000 - 19:45:11 EDT


> It feels like we run into these sorts of questions/problems on a
> fairly regular basis. I'm wondering therefore if any of the patterns
> gurus out there have systematically taken a look at some of the more
> pedestrian design patterns and seen how they are affected by JMM
> issues

I think Joe identified the most problematic widespread case: Many Java
frameworks (JavaBeans, Swing/Awt, Applets, Servlets, RMI activation
etc) make extensive use of no-arg constructors, leading to the
construct-then-set-fields or construct-then-init idioms. From a
concurrency stance, they are a bad idea, but from most other
perspectives they are a great idea. As in

  Applet a = (Applet)(class.ForName("MyApplet").newInstance());
  a.init();
  ...
  
So I do think that unsafe constructions surrounding no-arg
constructors are a real problem for JMM, without any apparent
solution, at least wrt automatically making them safe -- they don't
fit in with any constructor-centric safety guarantees. People simply
must use a lot of synchronization (or minimally, when it applies,
volatile ref fields) when using these kinds of components. Many people
in fact do so, but many others do not. Those who don't will have their
prgrams that work fine now on Pentiums and Sparcs start breaking under
new JMM, even on Pentiums and Sparcs (due to more aggressive permitted
register caching etc.)

I'm resigned to think that there's just nothing that can or should be
done about this beyond teaching people how and when to fix such
code. Also not that problems are mitigated by fact that programmers
are discouraged from ever creating new threads in most of the above
listed frameworks -- the safety problems associated with no-arg
constructors will be dwarfed by other problems if they do so.

> I don't know a lot about beans, but couldn't you write the value for the
> final into a static data structure before you invoke the constructor?
> Then the constructor could read the static data into a final field...

Well, that doesn't work in multithreaded contexts, but you could do it
as a ThreadLocal:

class Foo {
  public static final ThreadLocal nextBar = new ThreadLocal();
  final Bar bar;
  Foo() {
    bar = (Bar)(nextBar.get());
  }
}

caller:
  Foo.nextBar.put(new Bar());
  Foo f = new Foo();

It makes me cringe though!

Digression: If there were a way for a no-arg constructor to get a ref
to its caller, you could easily make these safe under current final
etc proposals -- the constructor could make callbacks to caller to
set initial/final values. I'm sure this will never happen though.

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



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