It is common for a class to have constant values defined as class fields (static and final) and then used in instances fields like in code bellow:

We all know that static fields are initialized first and then the instance ones, so it is no surprise until now. To be even more clear, I updated the code by adding code blocks with print statements:

that displays:

It is what we all expected so why I bother with posting about such simple things? It is because Elvis lives again. I get into trouble if I add a singleton instance at the beginning of the class:

The only difference is that we are using that singleton instance so I would expect the same result but instead I get:

In order to understand what happens we need to read When Initialization Occurs:

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.
  • T is a class and a static method declared by T is invoked.

and Detailed Initialization Procedure, step 3:

For each class or interface C, there is a unique initialization lock LC. The mapping from C to LC is left to the discretion of the Java Virtual Machine implementation. The procedure for initializing C is then as follows:

  1. Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC.
  2. If the Class object for C indicates that initialization is in progress for C by some other thread, then release LC and block the current thread until informed that the in-progress initialization has completed, at which time repeat this step.
  3. If the Class object for C indicates that initialization is in progress for C by the current thread, then this must be a recursive request for initialization. Release LC and complete normally.

After reading above sections, my understanding is that the following happens:

  1. RecursiveInitialization class is initialized because its main method is called.
  2. TROUBLE is a static field so it is initialized.
  3. TROUBLE is an instance of RecursiveInitialization so RecursiveInitialization should be initialized. There is already a class initialization in progress, so it completes normally. Instance field done is initialized with unboxed value of DONE, which is null and we receive that NullPointerException.

A simple fix is to move the singleton declaration and instantion after the static block:

and everything gets back to normal:

If this subjects interests you and you need more information about it, here is another example.

After seeing what can happen if I don’t pay attention to initialization details, I will be more careful in such situations.

Your thoughts are welcome

This site uses Akismet to reduce spam. Learn how your comment data is processed.