Java Class Loaders – Part 1

Java class loader - image of forklift

In this post, we’ll talk about class loaders in Java, how they work, and what the different types of class loaders are.

As Java programmers, it’s important for us to understand how class loaders work because they can affect how our code runs.

Introduction

Class loaders are a fundamental part of the Java Runtime Environment (JRE). They are responsible for loading Java classes into memory at runtime. Thanks to class loaders, the JVM doesn’t need to know about the underlying files or file systems to run Java applications.

A class loader is responsible for loading classes. When passed the binary/fully qualified name of a class, a class loader will try to find or generate data that defines the specified class. Typically the binary name is converted into a file name, and then a “class file” of that name is read from the underlying file system.

As a Java application starts, the classes aren’t all loaded into memory at once. They are loaded by the class loaders as and when they’re needed by the application.

Every Class object contains a reference to the ClassLoader that loaded it. We can find this by calling the getClassLoader() method of the Class class.

The class ClassLoader is an abstract class. We can implement our own class loaders to customise how classes are loaded into the JVM.

Types of Class Loaders

There are three main types of class loaders in Java:

  • The bootstrap class loader loads the core Java classes that are needed for the JVM to work.
  • The extension class loader loads classes that are part of Java extensions.
  • The application/system class loader loads classes that are part of the running application.

Let’s look at each of these class loaders in more detail.

Bootstrap Class Loader

Java classes are loaded by an instance of java.lang.ClassLoader. However, class loaders are also classes. So what loads the java.lang.ClassLoader?

This is where the bootstrap or primordial class loader comes into the picture. The bootstrap class loader is part of the core JVM. It is written in native code, and its behaviour differs slightly across JVMs.

The bootstrap class loader is the parent of all the other ClassLoader instances. It’s responsible for loading the core Java classes that the JVM needs. These classes are found in the rt.jar file and other libraries in the $JAVA_HOME/jre/lib directory (in Java 8).

Because the bootstrap class loader is written in native code it doesn’t display as a normal Java class. Some JVMs use null to represent the bootstrap class loader. null is also used for primitive types and void.

Extension Class Loader

The extension class loader is a child of the bootstrap class loader. It loads the extensions to the core Java classes from the JDK extensions directory. This is usually the $JAVA_HOME/lib/ext directory, or any directory specified in the java.ext.dirs system property. This is for Java 8 and below. Java 11 and later do not have extension directories.

The extension mechanism was removed in Java 9 and later versions. This means that the extension directories are no longer used to load Java extension classes. We now use the module system that was introduced in Java 9 to create and load custom libraries.

Application/System Class Loader

The application or system class loader loads the classes that are part of the application currently being run. It loads classes in the directories and JAR files specified by the CLASSPATH environment variable or the -classpath command line option. It’s also a child of the extensions class loader.

Example Code

The following code prints the class loaders for different classes.

import java.sql.DriverManager;
import java.util.ArrayList;

public class PrintClassLoaders {

    public static void main(String args[]) { 

        System.out.println("java.ext.dirs: "
            + System.getProperty("java.ext.dirs"));

        System.out.println("Classloader of ArrayList: "
            + ArrayList.class.getClassLoader());

        System.out.println("Classloader of String: "
            + String.class.getClassLoader());

        System.out.println("Classloader of this class: "
            + PrintClassLoaders.class.getClassLoader());

        System.out.println("Classloader of DriverManager: "
            + DriverManager.class.getClassLoader());

        System.out.println("Classloader of com.sun.nio.zipfs.ZipInfo: "
            + com.sun.nio.zipfs.ZipInfo.class.getClassLoader());

    }

} // end of class

Java 8 Output

Running this in Java 8 will give an output similar to the following (object addresses will differ on your machine):

java.ext.dirs: d:\jdk8\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
Classloader of String: null
Classloader of ArrayList: null
Classloader of this class: sun.misc.Launcher$AppClassLoader@73d16e93
Classloader of DriverManager: null
Classloader of com.sun.nio.zipfs.ZipInfo: sun.misc.Launcher$ExtClassLoader@70dea4e

We can see that the class loaders for String, ArrayList and DriverManager all return null. This generally represents the bootstrap class loader.

The PrintClassLoaders application class returns sun.misc.Launcher$AppClassLoader. This is the application/system class loader.

The ZipInfo class loader returns sun.misc.Launcher$ExtClassLoader. This is the extension class loader. The ZipInfo class was chosen at random to illustrate this.

Java 11 Output

Running the same code in Java 11 without recompiling will give an output similar to the following:

java.ext.dirs: null
Classloader of ArrayList: null
Classloader of String: null
Classloader of this class: jdk.internal.loader.ClassLoaders$AppClassLoader@30946e09
Classloader of DriverManager: jdk.internal.loader.ClassLoaders$PlatformClassLoader@5cbc508c
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/nio/zipfs/ZipInfo
        at PrintClassLoaders.main(PrintClassLoaders.java:24)
Caused by: java.lang.ClassNotFoundException: com.sun.nio.zipfs.ZipInfo
        ...

We see that the java.ext.dirs is null. Remember that the extension mechanism has been removed in Java 9 and later. That’s why we get a NoClassDefFoundError for com/sun/nio/zipfs/ZipInfo. Neither the directory nor the JAR files exist in Java 11. Obviously we could remove the line referring to the ZipInfo class.

The class loaders for String and ArrayList return null, which is the bootstrap class loader.

The PrintClassLoaders application class is loaded by the application/system class loader. This class loader is different to Java 8. It is now jdk.internal.loader.ClassLoaders$AppClassLoader. The AppClassLoader is responsible for loading classes from the application classpath and module path.

The DriverManager class loader now returns jdk.internal.loader.ClassLoaders$PlatformClassLoader. The PlatformClassLoader is a class loader introduced in Java 9 as part of the module system. It replaces the extension class loader. The PlatformClassLoader is responsible for loading classes from the Java SE Platform and JDK-specific tools. It is a parent/ancestor of the AppClassLoader. This mean that all platform classes are visible to it.

Conclusion

Next week we’ll look how class loaders work. We’ll look at creating a custom class loader implementation. We very seldom need to create our own class loaders. But we can implement subclasses of ClassLoader to customise the way the JVM loads classes.

Was this post useful? Let us know in the comments, and as always, stay safe and keep learning!

Leave a Comment

Your email address will not be published. Required fields are marked *

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.