Recursive initialization: static initializer doesn't get called when accessing a class field

Understanding class loading and static initializer calls

In what order are static initializers blocked?

So, I just tried to confirm this -

public class OOMErrorB extends OOMErrorA {
    public static int c = 10;

    static {
        System.out.println("Loading static B " + c);
        System.out.println(OOMErrorA.a);
    }

    public static void main(String[] args) {
        new OOMErrorB();
    }
}

      

Parent class -

public class OOMErrorA {
    public static int a = 20;

    static {
        a = a+ OOMErrorB.c;
        System.out.println("OOMErrorB.c " + OOMErrorB.c);
        System.out.println("loading OOMErrorA.a " + a);
    }
}

      

Now the Output of main method B is -

**

OOMErrorB.c 0
loading OOMErrorA.a 20
Loading static B 10
20

      

**

I can figure out that it loads class A first because it is a superclass and calls its static initializers,

now, since I am accessing OOMErrorB.c in the static block OOMErrorA, it should load and call the static initializer OOMErrorB. so OOMErrorB.c should be 10 and not 0.

What do I know about loading and initializing a class -

1) Class and gets loaded and variables are initialized to default values like for int - 0, Object - null.
2) Class field are initialized to specified values.
3) Static block gets called .

      

here in my program I can see the OOMErrorB class is loaded (step 1) but steps 2 and 3 are not running.

whereas according to the accepted answer for the link, it should call the static initializer OOMErrorB.

so that it finds itself in a cyclical dependence?

+3


source to share


1 answer


When accessed OOMErrorB.c

, OOMErrorB

does not load because it is already loaded (when the JVM originally loaded it to call the method main

). When the class is loaded into the JVM, it will not be loaded again. Therefore, a circular dependency does not arise: the OOMErrorB

static member c

is retrieved, which has not yet been initialized at this point.

You can check this section from the Java Language Specification about class initialization:



Because the Java programming language is multithreaded, initializing a class or interface requires careful synchronization, as some other threads may be trying to initialize the same class or interface at the same time. There is also the possibility that the initialization of a class or interface can be requested recursively as part of the initialization of that class or interface ; for example, a variable initializer in class A can call a method of unrelated class B, which in turn can call a method of class A. The Java virtual machine implementation is responsible for synchronization and recursive initialization by following a procedure.

The JVM has its own way of blocking the initialization of classes to prevent recursive initialization.

+1


source







All Articles