It is said that static blocks in java run only once when that class is loaded. But what does it actually mean? At which point is a class loaded by JVM (Java Virtual Machine)?
Is it when the main method in that class is called? And is it that all the super-classes of the same class are also loaded when the main method starts execution?
Consider that A extends B and B extends C. All have static blocks. If A has the main method, then what will be the sequence of execution of static blocks?
Class loading is done by ClassLoaders in Java which can be implemented to eagerly load a class as soon as another class references it or lazy load the class until a need of class initialization occurs. If Class is loaded before its actually being used it can sit inside before being initialized.
The parent-delegation architecture to class loading was implemented to aid security and to help programmers to write custom class loaders. Class loading loads, verifies, prepares and resolves, and initializes a class from a Java class file. Loading involves obtaining the byte array representing the Java class file.
Java classes aren't loaded into memory all at once, but when required by an application. At this point, the Java ClassLoader is called by the JRE and these ClassLoaders load classes into memory dynamically. Not all classes are loaded by a single ClassLoader.
A classloader can only actually load a class once! That means that it can only define it once. It can load it many times, but only the first time it will define it. The rest of the times it will load the existing instance it has already defined from the first time.
This is described in the Execution section of the JLS. Namely:
Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class. Initialization of an interface consists of executing the initializers for fields declared in the interface.
Before a class is initialized, its direct superclass must be initialized, but interfaces implemented by the class need not be initialized. Similarly, the superinterfaces of an interface need not be initialized before the interface is initialized.
So in your example, the static block of the "topmost" class (C
) runs first, then that of B
, then the most-derived one.
See that documentation for a detailed description of all the steps that go into loading a class.
(Classes get loaded when they are first actively used.)
I think the following example will solve all of your problems:
Before a class is initialized, its superclasses are initialized, if they have not previously been initialized.
Thus, the test program:
class Super {
static { System.out.print("Super "); }
}
class One {
static { System.out.print("One "); }
}
class Two extends Super {
static { System.out.print("Two "); }
}
class Test {
public static void main(String[] args) {
One o = null;
Two t = new Two();
System.out.println((Object)o == (Object)t);
}
}
prints:
Super Two false
The class One is never initialized, because it not used actively and therefore is never linked to. The class Two is initialized only after its superclass Super has been initialized.
For more details visit this link
Edit details: Removed confusing lines.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With