Java uses a dynamic class loading mechanism, meaning classes are loaded into memory only when required. This process is handled by a subsystem inside the JVM called the Class Loader Subsystem.
Class loading is essential because it:
- Converts
.classbytecode into JVM runtime objects - Ensures classes are loaded only once
- Provides security through class isolation
- Supports dynamic loading (plugins, frameworks, reflection)
The Class Loader Subsystem performs three major tasks:
- Loading
- Linking
- Initialization
+-----------------------------+
| Class Loader Subsystem |
+----------+-----------------------------+----------+
| Loading | Linking (Verify, Prepare, Resolve) | Initialization |
+----------+------------------------------------+---------------+
Let’s go deep into each.
The JVM performs three tasks here:
- Finding the class file (.class)
- Reading the bytecode
- Creating a Class object in the Method Area
Each loaded class is stored as a java.lang.Class object inside the JVM.
Class<?> clazz = Class.forName("com.example.Test");This triggers class loading.
Linking has three subphases:
Ensures bytecode is valid and safe:
- No illegal memory access
- No stack overflow
- Correct data types
- Follows JVM specifications
This ensures security and prevents JVM crashes.
Allocates memory for:
- Static variables
- Default values (0, null, false)
Example:
static int x = 10;During Preparation:
- Memory allocated for
x - Default value given:
x = 0
The actual value 10 is assigned in the initialization phase, not here.
Converts symbolic references into direct references.
Symbolic references appear in class files as strings:
java/lang/String → resolved to actual class reference
methodName → resolved to method pointer
This is when:
- Static blocks run
- Static variables get assigned final values
static int a = 10;
static {
System.out.println("Static block executed");
}Order of initialization:
- Default assignment (Preparation)
- Explicit assignment (Initialization)
- Static block execution
Java uses multiple class loaders arranged hierarchically.
Bootstrap ClassLoader
↑
Extension (Platform) ClassLoader
↑
Application (System) ClassLoader
- Part of JVM (native code, not Java code)
- Loads core Java classes (
rt.jaror modules)
Examples:
java.lang.*java.util.*java.io.*
- Loads classes from
JAVA_HOME/lib/ext - or JDK 9+: from platform modules
Examples:
- Java Cryptography Extensions
- Optional modules
- Loads classes from classpath:
classpath → . , target/classes , lib/*.jar
This is the class loader that loads your project code.
Example:
ClassLoader loader = MyClass.class.getClassLoader();Developers can create custom loaders for:
- Plugin systems
- Web containers (Tomcat)
- OSGi bundles
- On-the-fly code generation
Example:
class MyLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) {
// custom logic
}
}Java’s class loaders follow a parent delegation model:
- Child loader delegates request to parent
- Parent tries to load
- If parent fails → child tries
- Prevents core Java classes from being overridden
- Ensures stability and security
Flow:
Application Loader
↓ delegates
Platform Loader
↓ delegates
Bootstrap Loader
If Bootstrap cannot load → moves upward.
String s = "Java";Which class loader loads it?
Stringis part ofjava.lang- Loaded by Bootstrap ClassLoader
To check:
System.out.println(String.class.getClassLoader());Output:
null
(Null means Bootstrap loader)
A class is loaded when:
- You create an object
- You access a static variable
- You call a static method
- Reflection is used
- Class.forName() is called
Example:
Class.forName("com.example.Test");Forces class loading + initialization.
class A {
static int x = 10;
static {
System.out.println("static block");
}
}- Class loading → class metadata created
- Linking → static memory allocated (default 0)
- Initialization →
x = 10, then static block runs
Each web application has a separate class loader, so:
- Apps are isolated
- Hot reloading is possible
They use class loading for:
- Proxy generation
- Reflection
- Dependency injection
Custom class loaders load JARs at runtime.
A component of JVM that loads .class files into memory.
- Loading
- Linking → Verify, Prepare, Resolve
- Initialization
Child loader always delegates class loading to parent first.
| Bootstrap Loader | System Loader |
|---|---|
| Native code | Java code |
| Loads core classes | Loads application classes |
To force class loading + initialization.
-
Class loading is lazy and dynamic.
-
JVM uses a 3-phase process: Loading → Linking → Initialization.
-
Java follows a hierarchical class loader model.
-
Parent delegation ensures security, consistency, and prevents overriding core classes.
-
ClassLoaderis essential for frameworks, plugins, reflection, and dynamic loading.