Testing initialization safety of final fields Testing initialization safety of final fields multithreading multithreading

Testing initialization safety of final fields


I wrote the spec. The TL; DR version of this answer is that just because it may see 0 for y, that doesn't mean it is guaranteed to see 0 for y.

In this case, the final field spec guarantees that you will see 3 for x, as you point out. Think of the writer thread as having 4 instructions:

r1 = <create a new TestClass instance>r1.x = 3;r1.y = 4;f = r1;

The reason you might not see 3 for x is if the compiler reordered this code:

r1 = <create a new TestClass instance>f = r1;r1.x = 3;r1.y = 4;

The way the guarantee for final fields is usually implemented in practice is to ensure that the constructor finishes before any subsequent program actions take place. Imagine someone erected a big barrier between r1.y = 4 and f = r1. So, in practice, if you have any final fields for an object, you are likely to get visibility for all of them.

Now, in theory, someone could write a compiler that isn't implemented that way. In fact, many people have often talked about testing code by writing the most malicious compiler possible. This is particularly common among the C++ people, who have lots and lots of undefined corners of their language that can lead to terrible bugs.


From Java 5.0, you are guarenteed that all threads will see the final state set by the constructor.

If you want to see this fail, you could try an older JVM like 1.3.

I wouldn't print out every test, I would only print out the failures. You could get one failure in a million but miss it. But if you only print failures, they should be easy to spot.

A simpler way to see this fail is to add to the writer.

f.y = 5;

and test for

int y = TestClass.f.y; // could see 0, 4 or 5if (y != 5)    System.out.println("y = " + y);


I'd like to see a test which fails or an explanation why it's not possible with current JVMs.

Multithreading and Testing

You can't prove that a multithreaded application is broken (or not) by testing for several reasons:

  • the problem might only appear once every x hours of running, x being so high that it is unlikely that you see it in a short test
  • the problem might only appear with some combinations of JVM / processor architectures

In your case, to make the test break (i.e. to observe y == 0) would require the program to see a partially constructed object where some fields have been properly constructed and some not. This typically does not happen on x86 / hotspot.

How to determine if a multithreaded code is broken?

The only way to prove that the code is valid or broken is to apply the JLS rules to it and see what the outcome is. With data race publishing (no synchronization around the publication of the object or of y), the JLS provides no guarantee that y will be seen as 4 (it could be seen with its default value of 0).

Can that code really break?

In practice, some JVMs will be better at making the test fail. For example some compilers (cf "A test case showing that it doesn't work" in this article) could transform TestClass.f = new TestClass(); into something like (because it is published via a data race):

(1) allocate memory(2) write fields default values (x = 0; y = 0) //always first(3) write final fields final values (x = 3)    //must happen before publication(4) publish object                             //TestClass.f = new TestClass();(5) write non final fields (y = 4)             //has been reodered after (4)

The JLS mandates that (2) and (3) happen before the object publication (4). However, due to the data race, no guarantee is given for (5) - it would actually be a legal execution if a thread never observed that write operation. With the proper thread interleaving, it is therefore conceivable that if reader runs between 4 and 5, you will get the desired output.

I don't have a symantec JIT at hand so can't prove it experimentally :-)