Skip to Content
Course content

101: Class Loading Explained

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Think of the JVM not as a giant bucket that holds your entire app, but as a very efficient librarian. Imagine you're in a massive research library. You don't just wander the aisles hoping to stumble upon a book; you go to the front desk and request a specific title. If the local librarian doesn't have it, they don't just shrug; they call the regional branch. If the regional branch doesn't have it, they call the National Archive. Only when the National Archive says "we don't have it" does the local librarian finally check their own back shelf.

This is exactly how Java handles your classes. It doesn't load every single .class file in your project the moment you hit "Run." That would be a massive waste of memory. Instead, it uses a delegation model to find and load code on demand.

The Chain of Command: Who Actually Finds the Code?

In Java, there are three main "librarians" (ClassLoaders) working in a hierarchy. When your code refers to a class for the first time, the JVM kicks off this process:

  • The Bootstrap ClassLoader: This is the "National Archive." It's written in native code (C++) and loads the core Java APIs (like java.lang.String or java.util.ArrayList) from the rt.jar or the java.base module. It's the root of the tree.
  • The Platform ClassLoader: This is the "Regional Branch." It handles the extension classes—things that are part of the Java platform but aren't the absolute core basics.
  • The Application ClassLoader: This is your "Local Librarian." This is the one that looks at your CLASSPATH and finds the classes you actually wrote, like your UserAccount or PaymentProcessor classes.

Here is the crucial part: the Delegation Model. The Application ClassLoader doesn't just look for your class immediately. It asks the Platform ClassLoader first, which asks the Bootstrap ClassLoader. If the Bootstrap loader can't find it, it passes the request back down the chain. I've seen beginners get confused why they can't name their own class java.lang.String—it's because the Bootstrap loader always gets first dibs, and it's definitely going to find the real String class before the JVM ever looks at your code.

Why Java Doesn't Load Everything Up Front

You might wonder why we bother with this complex hand-off. It's all about Lazy Loading. Java only loads a class when it's actually referenced in the code. If you have a massive ExportToPDF class that only runs once a year during a tax report, the JVM won't waste a single byte of memory on it until that specific line of code is triggered.

This makes your apps start faster and keep a smaller memory footprint. However, it also means that a ClassNotFoundException usually doesn't happen when you start the program—it happens mid-execution, exactly at the moment the librarian realizes the book they were looking for simply doesn't exist in any of the archives.

Seeing the Hierarchy in Your Own Code

You can actually "interrogate" your classes to see who loaded them. If you call getClass().getClassLoader() on a class, you'll see the result. But there's a catch: because the Bootstrap ClassLoader is native code, it often returns null. When you see null, it's actually a sign that the "National Archive" handled it.

public class LoaderTest {
    public static void main(String[] args) {
        // This will likely print 'null' because it's loaded by the Bootstrap loader
        System.out.println("String loader: " + String.class.getClassLoader());

        // This will print the Application ClassLoader
        System.out.println("My class loader: " + LoaderTest.class.getClassLoader());
    }
}

It's a simple check, but it's the fastest way to visualize that your code and the Java core libraries are living in different "neighborhoods" of the JVM memory.




📋 Practical Task

Tracing the Loader Hierarchy of System and Custom Classes

Your goal is to write a small diagnostic program that proves the delegation model is working. You will create a program that prints the ClassLoader for three different types of classes to see the difference in how the JVM categorizes them.

Requirements:

  • Create a custom class named EmployeeRecord (it doesn't need any methods or fields).
  • In your main method, print the result of getClassLoader() for the following three classes:
    1. java.lang.Integer (A core Java class)
    2. java.util.Scanner (A utility class)
    3. Your custom EmployeeRecord class
  • Observe the output. You should see a null for the core class and a specific ClassLoader path for your custom class.

Bonus Challenge: Try to find a class that is loaded by the Platform ClassLoader (hint: look into javax.sql.DataSource) and add it to your list.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.