Java static initialization thread safety guarantee in language spec

It is commonly accepted that static initialization is thread safe. It is guaranteed to only happen once. I am however curious exactly where in the language spec does it state that there will be on visibility problems? This comes from http://www.ibm.com/developerworks/library/j-jtp03304/

This process guarantees that when a variable is written by one thread during a synchronized block protected by a given monitor and read by another thread during a synchronized block protected by the same monitor, the write to the variable will be visible by the reading thread. The JMM does not make this guarantee in the absence of synchronization

I have read similar things from a few other sources. In case of static initialization we do not use any synchronization. Assuming the initialized resource is effectively immutable, and we never write to it, there will be no synchronization used to access it ever and do not make it volatile. So where does the guarantee come from that any reading thread will not see a null pointer or partially initialized object? Obviously, since it happens during loading there is no possibility that another thread read the value before and sees a stale value, but what guarantees that results of the initialization do not stay in executing thread's local memory? Im curious to read the reason static initialization is safe.

EDIT: I understand static initialization is thread safe. Question is why and what guarantees that.

Jon Skeet
people
quotationmark

I believe this is effectively a result of the rules for class initialization in JLS 12.4.2. That involves synchronizing on a lock, only releasing it after executing the static initializers and field initializers. That lock acquisition and release then affects the "happens before" part of the thread model, via JLS 17.4.4 (I think - I'm not an expert on this).

Note that 12.4.2 states:

An implementation may optimize this procedure by eliding the lock acquisition in step 1 (and release in step 4/5) when it can determine that the initialization of the class has already completed, provided that, in terms of the memory model, all happens-before orderings that would exist if the lock were acquired, still exist when the optimization is performed.

people

See more on this question at Stackoverflow