Understanding the Seven Stages of Java Class Loading and Initialization
This article explains the seven stages of Java class loading—Loading, Verification, Preparation, Resolution, Initialization, Using, and Unloading—detailing each step, the underlying mechanisms, code examples, and practical considerations such as class initialization triggers and the distinction between symbolic and direct references.
The article introduces the lifecycle of a Java class from the moment its .class file is loaded into the JVM until it is unloaded, outlining seven distinct phases: Loading, Verification, Preparation, Resolution, Initialization, Using, and Unloading.
Loading (Loading) is the first phase, triggered either by pre‑loading of core libraries at JVM startup or by runtime loading when a class is first referenced. During loading the JVM obtains the binary stream of the .class file, stores class metadata, static variables, bytecode, and constant pool entries in the method area, and creates a java.lang.Class object (often placed in the heap, though HotSpot stores it in the method area).
Typical ways to obtain the binary stream include reading from a JAR/ZIP, downloading over the network (e.g., applets), generating at runtime (dynamic proxies), compiling JSPs, or even loading from a database.
Verification (Verification) ensures the byte‑code stream conforms to JVM constraints and does not threaten VM security. It checks file format, metadata, bytecode correctness, and symbolic references. For example, the JVM rejects a .class file whose major version exceeds the running JDK, throwing java.lang.UnsupportedClassVersionError .
Preparation (Preparation) allocates memory for static (class) variables in the method area and assigns them default zero values. Final static fields receive their constant values at this stage, while non‑final static fields are initialized later during the Initialization phase.
Resolution (Resolution) replaces symbolic references in the constant pool with direct references (pointers, offsets, or handles) that the VM can use at runtime. Symbolic references include fully qualified class names, field names and descriptors, and method names and descriptors.
Initialization (Initialization) executes the class initializer method <clinit>() , assigning user‑specified values to static variables and running static blocks. The JVM guarantees that initialization is performed only once and is properly synchronized across threads.
The article lists four situations that trigger active class initialization: (1) creating an instance with new , accessing or modifying a static field (except final constants), or invoking a static method; (2) reflective operations via java.lang.reflect ; (3) initializing a subclass whose superclass has not yet been initialized; (4) the JVM starting the class containing main() . All other references are passive and do not cause initialization.
Examples illustrate active vs. passive references:
public class SuperClass {
public static int value = 123;
static { System.out.println("SuperClass init"); }
}
public class SubClass extends SuperClass {
static { System.out.println("SubClass init"); }
}
public class TestMain {
public static void main(String[] args) {
System.out.println(SubClass.value); // triggers SuperClass init only
}
}Output:
SuperClass init
123Another example shows that creating an array of a class does not trigger initialization:
public class TestMain {
public static void main(String[] args) {
SuperClass[] arr = new SuperClass[10]; // no init output
}
}Finally, a constant‑propagation example demonstrates that accessing a static final constant does not cause the defining class to initialize because the constant value is inlined at compile time:
public class ConstClass {
public static final String HELLOWORLD = "Hello World";
static { System.out.println("ConstClass init"); }
}
public class TestMain {
public static void main(String[] args) {
System.out.println(ConstClass.HELLOWORLD); // prints value without init
}
}Output:
Hello WorldThroughout the article, the author emphasizes that the Loading phase offers the most control to developers, while the other phases are largely handled by the JVM implementation.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.