34

I recently came across this at work. While I am not sure it is really a good idea, I don't understand how static blocks are handled by the compiler.

Here is an example:

Consider that you have classes A and B:

public class A {

    public final static List<Integer> list;
    static {
        list = new ArrayList<>();
    }
}

public class B {

    public final static int dependsOnA;
    static {
        dependsOnA = A.list.size();
    }
}

And a main class that just reads B.dependsOnA.

The static block in B is dependent of the one in A, since it uses the list static variable.

Now, the code executes properly and no NullPointerException is raised at runtime. But what is the mechanism that ensures that list is initialized before it is potentially used elsewhere?

The Guy with The Hat
  • 10,836
  • 8
  • 57
  • 75
nsanglar
  • 1,632
  • 1
  • 14
  • 24
  • 3
    From a *design* point-of-view, I cordially suggest that it's not a good idea for class `A` to make *public* its `list` property, in the first place. Instead, I would have made it private, and provided *methods* in `A` which give all other classes "the things they need to know, and the ability to do the things that they need to do." A very important benefit is that, now, class `A` is both self-contained and self-describing. All of the code needed to ensure that class `A` is working correctly, is *in* class `A`, whose code is protected from interference or side-effects (like `B`). – Mike Robinson May 12 '15 at 13:39
  • 1
    ... also: "What can `A` do, and what can others do to `A`?" This question can now be answered, definitively, by looking *only* at `A`. The runtime difference between the two is negligible, but the design, IMHO, is much more robust and debuggable. (And, much less dependent upon "exactly when Java does this-or-that.") I submit that it's a good principle to say: "do not let other classes meddle in the affairs of other classes." Much as it is wise for humans ("who are crunchy, and taste good with Fava beans ...") not to meddle with dragons. – Mike Robinson May 12 '15 at 13:42
  • if list is already static wouldnt A.list.size() direct access be more efficient ? – Srinath Ganesh May 12 '15 at 14:02
  • 1
    @MikeRobinson The code in question will depend on when Java does this -or-that even if A.list was private. (Assuming you expose a method to add items to the list, and a method for getting the size of the array). Semantically the order java does this means that `B.dependsOnA` holds the number of items in A that was present the first time B was accessed. – Taemyr May 12 '15 at 14:03
  • 1
    @SrinathGanesh It would not do the same thing. See my comment to Mike. – Taemyr May 12 '15 at 14:04
  • Yes, and what I'm suggesting here is that "the `dependsOn` aspect of it" is what smells really bad to me. I would want to (re-)design the class structure such that no such dependencies existed, or needed to exist. Let each class be the master of its own kingdom. Now, I'm not saying that you can actually *do* that, in any deployed production application, but to my way of thinking, "what was done, here," is not a particularly good thing to have done. – Mike Robinson May 12 '15 at 14:14
  • *code executes properly and no NullPointerException is raised at runtime.* => in static block of class A you got *list = new ArrayList<>();* , **so there will never be a NPE exception** – Srinath Ganesh May 12 '15 at 14:19
  • @MikeRobinson That doesn't change anything in this question though. The list would still be created in A's static initializer, and B would still call `getList` to get it, and there would still be some mechanism to ensure that A's static initializer runs before the list is needed. – user253751 May 13 '15 at 09:55
  • ... unless `getList` used a "lazy initialization" technique, initializing the list (if necessary) the first time it's called to get the list. Lots and lots of ways to do this. And, in production apps, limited options for "changing it now." – Mike Robinson May 13 '15 at 15:26
  • @SrinathGanesh Never say never. If you look at my answer, you can easily see how even a `public static final List<> X = new ArrayList<>();` field can be observed to be null from the initialiser of another class. – biziclop May 14 '15 at 14:01

7 Answers7

34

The mechanism is described in detail here, but the five most important points are:

  1. Before a class is referenced, it needs to be initialised.
  2. If initialisation of a class has already begun (or if it's finished), it isn't attempted again.
  3. Before a class is initialised, all its superclasses and superinterfaces need to be initialised first.
  4. Static initialisers within a single class are executed in textual order.
  5. Implemented interfaces are initialised in the order in which they appear in the implements clause.

These rules completely define the order in which static blocks are executed.

Your case is rather simple: before you access B.dependsOnA, B needs to be initialised (rule 1), the static initialiser is then trying to access A.list, which triggers the initialisation of class A (again rule 1).

Note that there's nothing stopping you from creating circular dependencies this way, which will cause interesting things to happen:

public class Bar {
    public static int X = Foo.X+1;

    public static void main(String[] args) {
        System.out.println( Bar.X+" "+Foo.X); // 
    }

}

class Foo {
    public static int X = Bar.X+1;
}

The result here is 2 1 because the way the initialisation happens is this:

  1. Bars initialisation begins.
  2. Bar.Xs initial value is evaluated, which requires initialising Foo first
  3. Foos initialisation begins.
  4. Foo.Xs initial value is evaluated, but since Bars initialisation is already in progress, it isn't initialised again, Bar.Xs "current" value is used, which is 0, thus Foo.X is initialised to 1.
  5. We're back to evaluating Bar.Xs value, Foo.X is 1 so Bar.X becomes 2.

This works even if both fields were declared final.

The moral of the story is to be careful with static initialisers referring to other classes in the same library or application (referring to classes in a third party library or standard class library is safe as they won't be referring back to your class).

biziclop
  • 48,926
  • 12
  • 77
  • 104
9

The "mechanism" is the JVM's classloader, which will ensure that a class' initalization blocks are executed (with a global lock across the whole JVM) before returning control flow to where the class was first referenced. It will first load class A only after referenced, in this case when B's init block references A.list.

Grundlefleck
  • 124,925
  • 25
  • 94
  • 111
8

During execution of the static block of B, the runtime encounters A for the first time, and it will invoke the static block of A before it accesses A.list.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
  • 1
    The term `static` blocks is more common than `static` constructor. Not sure if anyone actually uses this term. – Chetan Kinger May 12 '15 at 13:34
  • 1
    Thanks Chetan, I changed it now. I use a lot of other languages (e.g. C#) where it's called a static constructor. – Glorfindel May 12 '15 at 13:36
7

No matter how you write the code, a static block is a static block and it will execute as part of the JVM loading a class.

When you say B.dependsOnA, B class starts geting loaded by the JVM and the static block in B gets called somewhere during this process. When you say dependsOnA = A.list.size();, class A starts getting loaded by the JVM and the static block in A will execute somewhere during this process which initializes the list. The statment list.size() will only execute after class A has been loaded completely by the JVM. Subsequently, the JVM can only finish loading class B after the static block in B completes.

Chetan Kinger
  • 15,069
  • 6
  • 45
  • 82
6

This is the job of the class loader. The class loading in java starts with the bootstrap classloader. This class loader first loads all the classes in the standard java library, the rt.jar.

Then the extension classloader is invoked. This loads all the classes from the extension jar files installed in a JVM ext directory. Now finally the classpath classloader is invoked.

The classpath classloader starts loading classes from the main class, the class that has the main method defined. Once it is loaded, it executes any static initializers in that class. While in the execution of the initializer, if it encounters any class that is not loaded, it will pause the execution of the static block, loads the class first, and finally resumes the execution of that static block.

So, there is no chance that any calls to non-loaded classes to occur. Let's see this with your own example, whose code is like this:

class A
{
    public final static List<Integer> list;
    static
    {
        System.out.println("Loaded Class A");
        list = new ArrayList<>();
    }
}

class B
{
    public final static int dependsOnA;
    static
    {
        System.out.println("Loaded Class B");
        dependsOnA = A.list.size();
    }
}

Here in this example, there is actually no main method, so these classes won't actually be loaded into the memory. Suppose, let's add the following main class to the above code.

class C
{
    static
    {
        System.out.println("Loaded Class C");
    }

    public static void main(String[] args)
    {
        System.out.println(B.dependsOnA);
    }
}

Let's see what this would produce in the output: http://ideone.com/pLg3Uh

Loaded Class C
Loaded Class B
Loaded Class A
0

That is, first the class C is loaded, because it had the main method. Once it is loaded, the static initializer of class C is invoked. Notice, however, that the main method is invoked after the static block of class C is loaded.

Now the main method, we printed the value of dependsOnA of class B. Now, the class loader stops executing that statement, and loads the class B, and executes it's static block, which in turn, assigns the dependsOnA variable with the value of the number of elements in the list of class A, which is not loaded.

So the class loader jumps from there, loads the class now, and invokes the static block of the class A, and a list is created. Now since there are no more classes to load, the class loader comes back to the static block of class B, and assignment is complete. Now finally, the control is now with the main method, and the value of dependsOnA is printed to the console.

Hope this helps.

Sri Harsha Chilakapati
  • 11,744
  • 6
  • 50
  • 91
5

Here we have some explaination Static Block in Java

If you call the A class first, the A static is called and A.list exists and will when B will call it.

If you call the B class first, the B static is called, cascading to the A call, calling its static block, where A.list is created.

We could see is its trickiest way: B > B.static > A > A.static > A.list exists

Community
  • 1
  • 1
Gary SEBASTIANI
  • 302
  • 1
  • 15
5

The working is very simple JVM class loader, which will ensure that a class static blocks are executed when the class is first referenced.
1.If you have executable statements in the static block, JVM will automatically execute these statements when the class is loaded into JVM.
2.If you’re referring some static variables/methods from the static blocks, these statements will be executed after the class is loaded into JVM same as above i.e., now the static variables/methods referred and the static block both will be executed.

Viraj Nalawade
  • 3,137
  • 3
  • 28
  • 44