Skip to content

Class Loader Subsystem

Table of Contents

  1. Class Loader Subsystem
  2. Responsibilities of the Class Loader 2.1 Loads .class Files into JVM Memory 2.2 Verifies Bytecode for Security 2.3 Links the Class 2.3.1 Verification 2.3.2 Preparation 2.3.3 Resolution 2.4 Initializes the Class
  3. Class Loading Process
  4. Built-in Class Loaders
  5. Parent Delegation Model
  6. Key Points
  7. Senior Developer Interview Questions — Scenario Based

1. Class Loader Subsystem

The Class Loader Subsystem is responsible for dynamically loading Java classes into the JVM at runtime. Instead of loading all classes at once, the JVM loads a class only when it is needed (lazy loading), which improves startup time and memory efficiency.


2. Responsibilities of the Class Loader

2.1 Loads .class Files into JVM Memory

  • Reads compiled Java bytecode (.class files) from different sources such as:

  • Local file system

  • JAR files
  • Network locations
  • Custom class loaders
  • Creates a Class object in the JVM representing the loaded class.
  • Stores the class metadata in Metaspace (Java 8+) and makes it available for execution.

2.2 Verifies Bytecode for Security

Before executing a class, the JVM verifies that its bytecode is valid and safe.

The verifier checks that:

  • The bytecode follows the JVM specification.
  • Variables are initialized before use.
  • Method calls have the correct number and type of arguments.
  • Stack operations are valid (no stack underflow/overflow).
  • Illegal memory access or type violations cannot occur.

This verification helps prevent malicious or corrupted bytecode from compromising the JVM.


After successful verification, the JVM links the class. Linking consists of three phases:

2.3.1 Verification

Ensures the bytecode is structurally correct and safe to execute.

2.3.2 Preparation

  • Allocates memory for static variables.
  • Assigns default values to static fields.

  • Numeric types → 0

  • booleanfalse
  • Object references → null

Example:

class Demo {
    static int count = 100;
}

During the Preparation phase:

count = 0;

The actual value (100) is assigned later during initialization.

2.3.3 Resolution

  • Converts symbolic references in the bytecode into direct memory references.
  • Resolves references to:

  • Classes

  • Methods
  • Fields
  • Interfaces

This allows the JVM to efficiently access the required classes and members during execution.


2.4 Initializes the Class

During initialization, the JVM executes:

  • Static variable assignments
  • Static initialization blocks (static {})

Example:

class Demo {
    static int count = 100;

    static {
        System.out.println("Static block executed");
    }
}

Initialization performs:

count = 100;
System.out.println("Static block executed");

This phase occurs only once for each class during its lifetime.


3. Class Loading Process

.class File
      │
      ▼
Loading
      │
      ▼
Linking
   ├── Verification
   ├── Preparation
   └── Resolution
      │
      ▼
Initialization
      │
      ▼
Class Ready for Execution

4. Built-in Class Loaders

Java uses a hierarchy of class loaders:

Class Loader Responsibility
Bootstrap ClassLoader Loads core Java classes such as java.lang.*, java.util.*, and other JDK libraries.
Platform (Extension) ClassLoader Loads platform-specific libraries and modules provided by the JDK (Java 9+).
Application (System) ClassLoader Loads classes from the application's classpath, including your project's compiled classes and dependencies.
Bootstrap ClassLoader
          │
          ▼
Platform ClassLoader
          │
          ▼
Application ClassLoader
          │
          ▼
Your Application Classes

5. Parent Delegation Model

Java follows the Parent Delegation Model to avoid loading the same class multiple times and to enhance security.

  1. A class loader first asks its parent to load the class.
  2. If the parent cannot find it, the current class loader attempts to load the class.
  3. This ensures that core Java classes are always loaded by the trusted Bootstrap ClassLoader.
Application ClassLoader
        │
        ▼
Platform ClassLoader
        │
        ▼
Bootstrap ClassLoader

6. Key Points

  • Loads classes dynamically when they are first needed.
  • Performs bytecode verification to ensure safety and correctness.
  • Links classes through Verification, Preparation, and Resolution.
  • Executes static field assignments and static blocks during initialization.
  • Stores class metadata in Metaspace.
  • Uses the Parent Delegation Model to prevent duplicate loading and improve security.

7. Senior Developer Interview Questions — Scenario Based

7.1 Scenario: Same Class Name, Different ClassLoaders

Question: Two ClassLoaders load a class with the same fully qualified name. Are they the same class?

Answer:

No.

In Java, a class is identified by:

Fully Qualified Class Name + ClassLoader

For example:

ClassLoader A + com.example.Employee

and

ClassLoader B + com.example.Employee

are considered different types by the JVM.

This can result in a ClassCastException even though both classes have the same fully qualified class name.


7.2 Scenario: Two Versions of the Same Library

Question: Your application requires library-v1.jar and library-v2.jar, and both contain com.example.Service. How could you load both versions simultaneously?

Answer:

Putting both JARs on the same classpath can cause class-loading conflicts because both contain the same fully qualified class name.

A possible solution is to use separate ClassLoaders so that each version is loaded in its own ClassLoader namespace.

For example:

ClassLoader A → library-v1.jar → com.example.Service
ClassLoader B → library-v2.jar → com.example.Service

Because the classes are loaded by different ClassLoaders, the JVM treats them as different types.

This approach is useful for plugin architectures and dependency isolation.


7.3 Scenario: Custom ClassLoader Loads java.lang.String

Question: A developer creates a custom ClassLoader and tries to load their own implementation of java.lang.String. What happens?

Answer:

The Parent Delegation Model causes the request to be delegated to the parent ClassLoader first.

The Bootstrap ClassLoader is responsible for core Java classes such as java.lang.String.

Therefore, the application's custom version cannot simply replace the trusted JDK String class.

This is one of the important security benefits of parent delegation.


7.4 Scenario: ClassCastException with the Same Class Name

Question: You see this exception:

java.lang.ClassCastException:
com.example.Employee cannot be cast to com.example.Employee

How is this possible?

Answer:

This can happen when two different ClassLoaders load com.example.Employee.

For example:

ClassLoader A → com.example.Employee
ClassLoader B → com.example.Employee

Although the class names are identical, the JVM considers them different types because their ClassLoaders are different.

Therefore, an object created using the class loaded by ClassLoader A cannot necessarily be cast to the class loaded by ClassLoader B.


7.5 Scenario: ClassNotFoundException

Question: Your application calls:

Class.forName("com.example.PaymentService");

and receives ClassNotFoundException. What would you investigate?

Answer:

You would investigate whether:

  1. The required JAR is present.
  2. The class is available on the application's classpath.
  3. The class name is correct.
  4. The appropriate ClassLoader can access the class.
  5. There is a dependency or packaging problem.

ClassNotFoundException generally indicates that the application attempted to load a class and the ClassLoader could not find it.


7.6 Scenario: NoClassDefFoundError

Question: A class was available during compilation, but at runtime the application throws NoClassDefFoundError. What could be the reason?

Answer:

A common reason is that the required class was available during compilation but is missing or unavailable at runtime.

You should investigate:

  • Runtime classpath
  • Missing JARs
  • Dependency packaging
  • ClassLoader visibility
  • Dependency version conflicts

ClassNotFoundException and NoClassDefFoundError are related but occur in different situations.


7.7 Scenario: Static Variable Value During Preparation

Question: Consider:

class Demo {
    static int count = 100;
}

What is the value of count during Preparation?

Answer:

During Preparation, the JVM assigns the default value:

count = 0

The value 100 is assigned during Initialization.

Therefore:

Preparation  → count = 0
Initialization → count = 100

7.8 Scenario: Static Block Execution

Question: Consider:

class Demo {

    static int count = 100;

    static {
        System.out.println("Static block executed");
    }
}

When does the static block execute?

Answer:

The static block executes during the Initialization phase of the class.

During initialization:

count = 100

is assigned and:

Static block executed

is printed.

Class initialization occurs only once for a particular class/ClassLoader combination.


7.9 Scenario: Two Threads Initialize the Same Class

Question: Two threads simultaneously trigger initialization of the same class. Can the static initialization block execute twice?

Answer:

No.

Class initialization is guaranteed by the JVM to occur only once for a given class/ClassLoader combination.

If multiple threads trigger initialization simultaneously, the JVM ensures that the initialization is properly synchronized.

One thread performs the initialization while other threads wait until initialization completes.


7.10 Scenario: ClassLoader Leak in an Application Server

Question: An application is repeatedly deployed and undeployed in an application server, and Metaspace usage keeps increasing. What could be the problem?

Answer:

A possible cause is a ClassLoader leak.

When an application is undeployed, its ClassLoader should become unreachable so that the classes loaded by it can eventually be unloaded.

However, if something still holds a reference to that ClassLoader or its classes, the ClassLoader may remain reachable.

Possible causes include:

  • Static references
  • Threads
  • ThreadLocal values
  • Caches
  • JDBC drivers
  • Executors
  • Listeners

This can prevent class unloading and contribute to increasing Metaspace usage.


7.11 Scenario: Class Loaded from the Wrong JAR

Question: Production is unexpectedly using an older version of a class even though a newer JAR is deployed. How would you investigate it?

Answer:

First, determine which ClassLoader loaded the class.

You can inspect:

Class<?> clazz = com.example.Service.class;

System.out.println(clazz.getClassLoader());
System.out.println(
    clazz.getProtectionDomain()
         .getCodeSource()
         .getLocation()
);

This can help identify:

  • Which ClassLoader loaded the class.
  • Which JAR or location the class came from.

Then investigate:

  • Classpath ordering
  • Duplicate JARs
  • Application server ClassLoaders
  • Dependency conflicts
  • Parent/child ClassLoader relationships

7.12 Scenario: Parent ClassLoader Has a Class

Question: The Application ClassLoader has its own version of a class, but the parent ClassLoader already has a class with the same name. Which class is normally loaded?

Answer:

Under the Parent Delegation Model, the Application ClassLoader first delegates the request to its parent.

If the parent successfully loads the class, the child normally uses the parent's class rather than loading its own version.

The flow is:

Application ClassLoader
        ↓
Platform ClassLoader
        ↓
Bootstrap ClassLoader

The child attempts to load the class itself only when the parent cannot find it.


7.13 Scenario: Metaspace Keeps Increasing

Question: Your application dynamically generates many classes and Metaspace usage keeps increasing. What would you investigate?

Answer:

I would investigate whether the application is continuously creating new classes and whether their ClassLoaders can be garbage collected.

I would particularly look for:

  • Dynamically generated classes
  • Frequently created ClassLoaders
  • ClassLoader leaks
  • Static references
  • ThreadLocal references
  • Caches holding application classes
  • Application redeployment issues

If the ClassLoader remains reachable, its loaded classes cannot be unloaded.


7.14 Scenario: Find Which ClassLoader Loaded a Class

Question: You suspect that the wrong ClassLoader loaded a class in production. How can you identify the ClassLoader?

Answer:

Use:

Class<?> clazz = MyClass.class;

System.out.println(clazz.getClassLoader());

You can also inspect the class's code source:

System.out.println(
    clazz.getProtectionDomain()
         .getCodeSource()
         .getLocation()
);

This helps determine both the ClassLoader and the location from which the class was loaded.


7.15 Scenario: Plugin Architecture

Question: You are building a plugin-based application where each plugin may use different library versions. Why might separate ClassLoaders be useful?

Answer:

Separate ClassLoaders provide dependency isolation.

For example:

Application ClassLoader
        │
        ├── Plugin ClassLoader A → Plugin A + library-v1
        │
        └── Plugin ClassLoader B → Plugin B + library-v2

Each plugin can have its own dependency version without necessarily conflicting with another plugin.

However, objects and classes crossing ClassLoader boundaries must be designed carefully because the JVM treats classes loaded by different ClassLoaders as different types.


8. Quick Senior Interview Revision

The most important scenarios to remember are:

  1. Same fully qualified name + different ClassLoader → Different types
  2. Same library with multiple versions → Separate ClassLoaders can provide isolation
  3. Parent has the class → Parent Delegation normally uses the parent's class
  4. ClassNotFoundException → Class could not be found when explicitly requested
  5. NoClassDefFoundError → Class was available/expected but is unavailable at runtime
  6. Static variable during Preparation → Default value
  7. Static assignment/static block → Initialization
  8. Repeated deployment + increasing Metaspace → Investigate ClassLoader leak
  9. Wrong JAR loaded → Check ClassLoader and CodeSource
  10. Same class name but different ClassLoaders → Possible ClassCastException