Careeroza
Class Loading
From .class to Running Code
The JVM loads classes lazily: a class is loaded the first time it is needed. Loading has three phases.
Main.class ─► LOADING ─► LINKING ───────────────────────────► INITIALIZATION
(read bytes, verify → prepare → resolve (run static blocks,
create Class (bytecode (static (symbolic refs assign static fields)
object) is safe) defaults) → real refs)Class Loader Hierarchy
| Loader | Loads | Name |
|---|---|---|
| Bootstrap | core JDK classes (java.lang, java.util) — written in native code | shown as null |
| Platform | other JDK modules (java.sql, java.xml...) | platform |
| Application (system) | your classes and jars on the classpath | app |
| Custom | plugins, hot reload (Tomcat web apps, Spring DevTools) | any |
Loaders use parent delegation: a loader first asks its parent, and only loads the class itself if the parent cannot. This stops anyone from replacing java.lang.String with their own class.
See It Yourself
Example
A class is initialized only when first used. Its static block runs exactly once.
public class Main {
public static void main(String[] args) {
System.out.println("String loaded by: " + String.class.getClassLoader());
ClassLoader app = ClassLoader.getSystemClassLoader();
System.out.println("System loader: " + app.getName() + ", parent: " + app.getParent().getName());
System.out.println("java.sql.Date loaded by: " + java.sql.Date.class.getClassLoader().getName());
System.out.println("main started, Config not used yet");
System.out.println("Reading constant: " + Config.APP_NAME); // compile-time constant: no init
System.out.println("Calling method: " + Config.timeout()); // triggers initialization
System.out.println("Calling again: " + Config.timeout()); // static block does not run again
}
}
class Config {
static final String APP_NAME = "ShopEase"; // inlined by the compiler
private static int timeout;
static {
System.out.println(" [Config static block runs]");
timeout = 30;
}
static int timeout() { return timeout; }
}Output
String loaded by: null System loader: app, parent: platform java.sql.Date loaded by: platform main started, Config not used yet Reading constant: ShopEase [Config static block runs] Calling method: 30 Calling again: 30
Common Errors
| Error | Meaning |
|---|---|
ClassNotFoundException | loading by name at runtime failed (Class.forName("x")), jar missing |
NoClassDefFoundError | class was present at compile time but missing at runtime, or its static init failed earlier |
ExceptionInInitializerError | a static block or static field initializer threw |
UnsupportedClassVersionError | compiled with a newer Java than the one running it (e.g. built on 21, run on 17) |