Class Loading Phases: Load, Link, Initialize
Walk through loading, verification, preparation, resolution, and initialization of classes.
Class Loading Phases: Load, Link, Initialize is a free Java Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Class Loading Lifecycle
A Java class goes through three phases before it can be used: Loading (find and read the bytecode), Linking (verify, prepare, resolve), and Initialization (run static initializers).
Phase 1: Loading
The ClassLoader reads the .class file (from filesystem, JAR, network, or generated bytecode) and creates a Class<?> object in the heap representing it.
// Trigger loading explicitly:
Class<?> c = Class.forName("com.example.MyService");
// The JVM delegates to the appropriate ClassLoader to find and load MyService.classPhase 2a: Verification
The bytecode verifier checks that the loaded bytecode is structurally valid, type-safe, and follows JVM spec rules. Invalid bytecode (e.g., manipulated with ASM incorrectly) causes VerifyError.
Phase 2b: Preparation
The JVM allocates memory for static fields and sets them to their default values (0, false, null). Static initializers have NOT run yet at this stage.
public class Config {
static int timeout = 30; // after preparation: timeout = 0 (default)
static String host = "db"; // after preparation: host = null
// Both get their real values only after Initialization
}Phase 2c: Resolution
Symbolic references (class names, method signatures) in the constant pool are replaced with direct references (pointers) to the actual classes and methods. May be deferred (lazy resolution).
Phase 3: Initialization
Static initializers (static {} blocks) and static field assignments run in textual order. This is when timeout = 30 and host = "db" actually execute.
public class Config {
static int timeout;
static String host;
static {
timeout = Integer.parseInt(System.getenv("TIMEOUT"));
host = System.getenv("DB_HOST");
System.out.println("Config initialized");
}
}Class Initialization Triggers
Initialization runs on first: (1) instance creation, (2) static field access (non-constant), (3) static method call, (4) reflection via Class.forName() (with initialize=true), (5) subclass initialization.
// forName with initialize=false skips static initializers:
Class<?> c = Class.forName("com.example.MyService", false, loader);The <clinit> Method
The JVM generates a <clinit> method (class initializer) from all static initializers and static field assignments. It runs exactly once and is thread-safe — the JVM guarantees mutual exclusion.
ExceptionInInitializerError
If a static initializer throws an exception, the JVM wraps it in ExceptionInInitializerError. Subsequent attempts to use the class throw NoClassDefFoundError.
static {
if (System.getenv("DB_URL") == null)
throw new RuntimeException("DB_URL not set"); // wrapped in ExceptionInInitializerError
}Static Initialization Order
Static initializers run in textual order. Circular class dependencies during initialization can cause partially initialized classes — a known gotcha with the Initialization-on-Demand Holder pattern.
class A {
static final int X = B.Y + 1; // accesses B before B is initialized!
}
class B {
static final int Y = A.X + 1; // circular!
}Observing Class Loading
Enable class loading log output with -Xlog:class+load=info (JVM 9+) to see which classes are loaded, from where, and by which ClassLoader.
// JVM flag:
// java -Xlog:class+load=info:file=classload.log MyApp
// Output lines like:
// [info][class,load] com.example.MyService source: file:///app/app.jarQuick Check
During which phase do static initializers execute?
Recap
Load: read bytecode. Link: verify → prepare (zero defaults) → resolve (symbolic refs). Initialize: run <clinit>. Initialization is triggered by first use and is thread-safe. Circular dependencies during init cause subtle bugs.
Frequently asked questions
Is the “Class Loading Phases: Load, Link, Initialize” lesson free?
Yes — the full text of “Class Loading Phases: Load, Link, Initialize” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “Class Loading Phases: Load, Link, Initialize”?
Walk through loading, verification, preparation, resolution, and initialization of classes. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Class Loading Phases: Load, Link, Initialize” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Class Loading Phases: Load, Link, Initialize
- ClassLoader Hierarchy and Custom Loaders
- Inspecting Bytecode with javap
- JIT Compilation and Tiered Compilation