JavaMemoryModel: Class initialization safety is hard

From: Bill Pugh (pugh@cs.umd.edu)
Date: Fri Jul 09 1999 - 11:00:39 EDT


At 11:30 AM -0700 7/5/99, Paul Haahr wrote:
> > By the way, we should also guarantee class initialization safety:
> > that lack of synchronization doesn't allow you to see the results of
> > an incompletely executed class initializer.
>
>My naive understanding is that that's guaranteed by the rules in 12.4.2
>of the JLS, which requires a class initializer to synchronize on the
>class object.
>
>The worry, I guess, is of a second processor seeing a class as ``fully
>initialized,'' but not seeing all the static fields as fully initialized.
>But, on the other hand, to properly the detect the class as initialized,
>that processor is probably required to insert a memory barrier.

Considering the following example on a machine in which dependent
reads can be reordered (equivalently, can read from stale cache
lines):

class Foo {
        static Object x;
        }

class Bar {
        static int y = 17;
        int z = 42;
        public int hashCode() { return y * z; }
        }

Thread 1:

        Foo.x = Class.forName("Bar").newInstance();

Thread 2:

        int a = Foo.x.hashCode();

Consider the following sequence of events

Thread 1 starts running
Thread 1 loads, links and initializes Bar
        (including running the clinit method of Bar)
Thread 1 allocates and constructs an instance of Bar
Thread 1 stores a reference to the newly allocated instance into Foo.x

Thread 2 Reads Foo.x, gets the value written by Thread 1
        Note that thread 2 has not done a memory barrier since before thread 1
        started to load Bar. So it might see stale values for all of the writes
        done by thread 1 (other than the write to Foo.x, which we happened to
        see).
Thread 2 reads the vtbl entry (is this null?)
Thread 2 tries to dispatch through the vtbl. Any or all of the data structures
        created by the loading of Bar might be stale. This includes the pointer
        to the bytecode for the hashCode method, the actual bytecode itself,
        jit'd code, and all of the other fields that make up the class
        structure.
Thread 2 runs the hashCode method, and could see stale values for both y and z.

In some ways, seeing a stale value for y is harder to fix than seeing
a stale value for z. It is clear that the read of y is dependent on
the value of Foo.x that is read, and can't be reordered on Sparc RMO.
Is the read of z a dependent read? Hard to say.

        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