Java Exception Handling

Java Exception Handling – ClassNotFoundException

Today we continue our detailed Java Exception Handling series with a closer look at the java.lang.ClassNotFoundException. Unlike many Java errors that can occur in a variety of scenarios, the ClassNotFoundException can only be thrown as a result of three different method calls, all of which handling loading classes by name.

In this article we’ll dig into the ClassNotFoundException in more detail, looking at where it sits in the Java Exception Hierarchy, along with some functional code samples illustrating how ClassNotFoundExceptions are thrown, so let’s get this party started!

The Technical Rundown

When Should You Use It?

As mentioned, the ClassNotFoundException can only occur as a result of three different methods failing to load the specified class. The three methods in question are as follows (we’ve obviously excluded their respective overloads):

Therefore, the only time a ClassNotFoundException should be raised is when calling one of the above methods with an invalid class name argument. We’ll start with our full code sample below, after which we’ll break it down in a bit more detail and look at how each method is used and might potentially throw a ClassNotFoundException:

Since we have three built-in java.lang methods to test, we’ve written three of our own testing methods to coincide with each. We start with the getClassByName(String name) method:

This is an extremely basic method (most of the code is for error handling, in fact). As you can see, the purpose is to act as a wrapper and exception catcher for the Class.forName(String className) method call.

Next, we have the getSystemClassFromLoaderByName(String name) method, which is a wrapper to call the ClassLoader.findSystemClass(String name) method:

As it happens the ClassLoader.findSystemClass(String name) method is protected, which means it can only be accessed from within the class itself, its package, or a subclass that extends ClassLoader. Since our calling code is within a different package (io.airbrake compared to java.lang), we cannot make a direct call to ClassLoader.findSystemClass(String name).

The solution here is to create our own class that extends ClassLoader, which will inherit all the methods from the base ClassLoader class, and allowing us to create our own class method that wraps the base ClassLoader.findSystemClass(String name) call. The MyClassLoader class serves this purpose by extending ClassLoader:

Just like the ClassLoader.findSystemClass(String name) method, our findSystemClassByName(String name) method throws ClassNotFoundException, which will propagate up through the call stack to our calling code.

Finally, the getClassFromLoaderByName(String name) method is a wrapper for the ClassLoader.loadClass(String name) method. Unlike the previous built-in method, this one is not protected, but it is an instance method, so we need to instantiate a new MyClassLoader instance on which we can call loadClass(String name):

To test our code out we are passing a class name to each of our three methods, then outputting the returned class name. If no class was found, the return value is null:

We first start by passing a very common and widely used class: java.lang.Integer. This is just to verify that all our methods are working and that classes are retrievable via the underlying, wrapped methods. The output confirms that all three work as expected:

Now we change the class name to something that doesn’t exist; in this case, io.airbrake.InvalidClassName:

As you can probably guess, all three of our methods run into trouble and are unable to retrieve a class by that name, resulting in three ClassNotFoundExceptions in the output (along with null return values):

The Airbrake-Java library provides real-time error monitoring and automatic exception reporting for all your Java-based projects. Tight integration with Airbrake’s state of the art web dashboard ensures that Airbrake-Java gives you round-the-clock status updates on your application’s health and error rates. Airbrake-Java easily integrates with all the latest Java frameworks and platforms like Spring, Maven, log4j, Struts, Kotlin, Grails, Groovy, and many more. Plus, Airbrake-Java allows you to easily customize exception parameters and gives you full, configurable filter capabilities so you only gather the errors that matter most.

Check out all the amazing features Airbrake-Java has to offer and see for yourself why so many of the world’s best engineering teams are using Airbrake to revolutionize their exception handling practices!