Difference between thread's context class loader and normal classloader
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Java, class loading is a crucial aspect that dictates how Java applications load classes into the Java Virtual Machine (JVM) at runtime. Java uses a hierarchical class loader model, meaning that class loading happens in a parent-child hierarchy. Understanding the nuances between a thread's context class loader and a normal class loader can be critical for developers dealing with complex Java applications, especially those that involve multi-threading, class loading issues, or need custom class loading strategies.
Normal Class Loader
Overview
A normal class loader refers to the standard class loading mechanism provided by the Java environment. The JVM provides a set of standard class loaders:
- Bootstrap Class Loader: It is responsible for loading core Java classes located in the
rt.jarfile. - Extension Class Loader: This class loader loads classes from the extensions directory (
$JAVA_HOME/lib/ext). - Application Class Loader: Also known as the System class loader, it loads classes from the classpath specified during the application startup.
How it Works
The normal class loader follows the delegation model. When a class loader receives a class request, it delegates the request to its parent in the hierarchy if possible. This approach prevents duplicate class loading and maintains class uniqueness in the JVM:
Limitations
- Limited Flexibility: The rigid hierarchy can lead to challenges when specific classes need to be loaded in different contexts, such as in dynamic module systems or customized environments.
- Limited Scope: The class loader configuration is static and cannot easily incorporate non-standard ways of loading classes dynamically at runtime.
Thread's Context Class Loader
Overview
The thread context class loader concept allows a program to influence the class loading mechanism used by threads. It was introduced to address situations where the standard delegation model of class loading is not suitable, particularly in complex Java EE environments and distributed systems where different resource environments may require different class loading logic.
How it Works
Every thread in Java has an associated contextClassLoader, which by default is set to the parent thread's context class loader. It can be accessed and modified using the following methods:
- Getting Context Class Loader:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - Setting Context Class Loader:
Thread.currentThread().setContextClassLoader(customClassLoader);
The context class loader is utilized when:
- Loading service provider classes (as seen in SPI implementations).
- Accessing resources or classes via third-party libraries that rely on this loader.
Code Example
In this example, the thread will print the current context class loader, which could be customized before the thread execution.
Advantages
- Customizability: Developers can select or implement custom class loaders suitable for specific tasks or environments without disturbing the parent-child hierarchy.
- Flexibility: It provides the potential to switch or change class loaders at runtime, enhancing adaptability in modular systems.
Use Cases
- Java EE Containers: They often use thread context class loaders to allow application-specific class loading without affecting the container's global context.
- Third-party Libraries: Some libraries rely on thread context class loaders to access their resources dynamically.
Key Differences
| Feature | Normal Class Loader | Thread's Context Class Loader |
| Hierarchy | Follows strict parent-child hierarchy in loading classes. | Does not follow hierarchy, set per-thread basis. |
| Default Permission | Determined by JVM's class loader structure. | Initially inherited from the parent thread, can be customized. |
| Use Case | Suitable for typical applications with standard classpath inflows. | Ideal for more dynamic environments like Java EE, SPI, etc. |
| Flexibility | Limited scope for runtime dynamic adjustments. | Flexible for use in modular systems and specific runtime environments. |
| Implementation Control | Offers limited control as it's tightly integrated with JVM. | Developers can exercise more control over the class loading process. |
Conclusion
Understanding the difference between a thread's context class loader and the normal class loader is essential for efficiently managing class loading in Java, especially in complex applications. While the normal class loader is sufficient for most applications, the context class loader offers enhanced flexibility and adaptability, making it a powerful tool in the hands of experienced Java developers working with complex systems.

