Class loading and the loaders
Classes arrive lazily, in three steps, through a chain of loaders that always ask their parent first.
Open this lesson in the learning hubKey points
- Three steps: load the bytes, link them (verify, prepare, resolve), then initialise by running static blocks.
- It is lazy. A class is initialised on first active use, not at startup. That is why a broken static block fails late and confusingly.
- Verification is a real security boundary. Corrupt or hand-crafted bytecode is rejected before a single instruction runs.
- Three loaders since Java 9: bootstrap (reported as
null), platform, and application for your classpath. - Each loader asks its parent first. That is parent delegation, and it stops your own String class replacing the real one.
- Class identity is name plus loader. The same file loaded twice is two different types - the cause of baffling cast errors.
Example
public class Main {
static class Config {
static String name = "settings"; // not a compile-time constant
static { System.out.println("2. Config initialised - on first active use"); }
}
public static void main(String[] args) {
System.out.println("1. main running, Config not touched yet");
System.out.println("3. Config.name = " + Config.name);
System.out.println();
System.out.println("String <- " + String.class.getClassLoader());
System.out.println("java.sql.Driver <- " + java.sql.Driver.class.getClassLoader());
System.out.println("Main <- " + Main.class.getClassLoader());
System.out.println("parent of that one <- " + Main.class.getClassLoader().getParent());
System.out.println();
System.out.println("null means the bootstrap loader, written in C++ inside the VM.");
}
}
Classes load late, verify hard, and delegate upwards.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the JVM course, and every lesson in it is listed on the JVM contents page.