There is an example in <<JCP>> 3.5 which demonstrates improper publish.
public class Holder{
private int n;
public Holder(int n){this.n = n;}
public void assertSanity(){
if(n != n){
throw new AssertionError("This statement is false.");
}
}
}
another class publish Holder object.
public Holder holder;
public void initialize(){
holder = new Holder(42);
}
Holder object was not properly published. Two things could go wrong with the improperly published object.
1. Another thread could see the stale value for the "holder" field. The stale value could be null or older reference even though a new value has been placed in "holder".
2. Another thread could see a up-to-date value for "holder" reference, but see a stale values for its state.
My understanding follows.
The creating an object order is:
1. load all classes,including super classes and C itself. (only once)
2. Perform static initialization (only once)
3. allocate memory space and swipe to zero.
4. Assigns the parameter variables of called constructor of class C.
6. Process any explicit or implicit constructor invocation(a call to this() or super() in the constructor);
7. Initialize the variables in class C.
8. Perform instance initialization in class C.
9. Execute called constructor of class C.
The action creating an object is not atomic. When the thread creating an object finishes to execute Step 3, another thread begin to call the object, the object reference is up-to-date, but the state values are default. So the state values are invalid even though the object reference is right. It is also initialization unsafety.
According to <<Think in Java>>, if a filed is final, compiler ensure that it can not be used before being given an initialized value. I understand that the initialization value can not just be default ZERO value, must be value after finishing executing a constructor. Of course, the initialization value could be default ZERO value after finishing construct. <<JCP>> describes that the Java Memory Model offers a special guarantee of initialization safety for a final field. So since an immutable object needs initialization safety, its all field must be final. In another words, that all fields are final ensures that the object initialization is safe.