Re: JavaMemoryModel: Class initialization safety is hard

From: Bill Pugh (pugh@cs.umd.edu)
Date: Fri Jul 09 1999 - 17:54:35 EDT


At 1:48 PM -0700 7/9/99, Joshua Bloch wrote:
>Bill,
>
> I don't understand your example, but I do agree with Doug: the current
>JLS (S. 12.4.2, P. 226) *does* take care of class initialization. Roughly
>speaking, it says that at every possible "point of initialization" [their
>wording], a thread must (effectively) execute a synchronized method that
>initializes the class if it's not already initialized. This seems
>sufficient (if potentially costly).
>
> Josh

Did you mean Paul Haahr? I didn't see a message from Doug on the
topic of class initialization safety.

I disagree with your analysis above. I believe the appropriate
section is 12.4.1:

>12.4.1 When Initialization Occurs
>
>A class or interface type T will be initialized at its first active
>use, which occurs if:
>
>* T is a class and a method actually declared in T (rather than
>inherited from a superclass) is invoked.
>* T is a class and a constructor for class T is invoked, or U
>is an array with element type T, and an array of type U is created.
>* A non-constant field declared in T (rather than inherited
>from a superclass or superinterface) is used or assigned. A constant
>field is one that is (explicitly or implicitly) both final and
>static, and that is initialized with the value of a compile-time
>constant expression (15.27). Java specifies that a reference to a
>constant field must be resolved at compile time to a copy of the
>compile-time constant value, so uses of such a field are never
>active uses. See 13.4.8 for a further discussion.
>

Section 12.4.2 would prevent another thread from running the clinit
method of a class if another thread had already started it. But it
doesn't guarantee class initialization safety.

The problem is the word _first_ in:

>A class or interface type T will be initialized at its first active
>use, which occurs if:

What does "first" mean in a multi-processor system? This is worse
than general relativity: it isn't just that different yardsticks are
used to measure time on different processors. Time doesn't even have
the same linear ordering on different processors.

So when processor 1 creates an instance of Bar, that is the first
active use of Bar, and the class is initialized. Processor 1 then
stores the reference into Foo.x, which is read by processor 2. When
processor 2 invokes Foo.x.hashCode(), that isn't the first active use
of Bar; someone must have previously made an active use of Bar.

In fact, the spec allows you to get away removing checks for class
initialization in instance methods, since you are guaranteed that the
class must have been initialized (when the instance was created)
before the instance method was invoked.

If the spec said:
>A class or interface type T must be seen asinitialized in thread S
>before its first active use in thread S

then we would be guaranteed a form of class initialization safety.
But as it stands, it is not guaranteed.

I ran the problem of class initialization safety past Guy Steele, and
he didn't object to me raising it as an issue with the current spec.

        Bill

-------------------------------
This is the JavaMemoryModel mailing list, managed by Majordomo 1.94.4.

To send a message to the list, email JavaMemoryModel@cs.umd.edu
To send a request to the list, email majordomo@cs.umd.edu and put
your request in the body of the message (use the request "help" for help).
For more information, visit http://www.cs.umd.edu/~pugh/java/memoryModel



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