0Pricing
Java Academy · Lesson

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.class

Phase 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.jar

Quick 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

  1. Class Loading Phases: Load, Link, Initialize
  2. ClassLoader Hierarchy and Custom Loaders
  3. Inspecting Bytecode with javap
  4. JIT Compilation and Tiered Compilation
← Back to Java Academy