ClassNotFoundException, explained and fixed

ClassNotFoundException is thrown when code explicitly asks for a class by its name string, through Class.forName(...), a framework's configuration, or a driver manager, and the class loader cannot find it. The overwhelmingly common case is a JDBC driver: Class.forName("com.mysql.cj.jdbc.Driver") or a datasource configuration naming a driver whose jar was never added to the project. The class name in the message, character for character, is the first thing to verify.

How to find the cause

  1. Check the name in the message against the current library: names change between versions. MySQL's driver class is com.mysql.cj.jdbc.Driver in Connector/J 8, the old com.mysql.jdbc.Driver belongs to version 5. A name copied from an old tutorial into a new project fails exactly like this.
  2. Confirm the jar is on the runtime classpath, not merely downloaded: list the application's dependencies (mvn dependency:tree, Gradle's dependencies report, or inspect the deployed lib folder) and find the artifact that contains the class.
  3. For JDBC specifically, note that modern drivers register themselves automatically via the service loader; an explicit Class.forName is often unnecessary, and removing the call plus having the jar present is enough. If it still fails, the jar truly is absent.

The fixes, in order

  1. Add the correct dependency for the database or library in the build file, at a version compatible with the server, and rebuild so the jar is packaged with the application.
  2. Correct the class name to the one the installed version provides; vendor documentation for the exact version lists it, and the jar itself can be listed (jar tf driver.jar | grep Driver) to see the real path.
  3. In application servers and plugin systems, place the driver where the container expects shared libraries, or bundle it in the application, following the server's own rule; a driver visible to the wrong classloader fails the same way.
  4. Check for typos introduced by configuration files: a properties or YAML entry with a trailing space or a stale copied name is a frequent source, the message prints the string it actually tried.

Common questions

How is this different from NoClassDefFoundError? This exception is thrown by an explicit by-name lookup and is checked, the calling code must handle it. NoClassDefFoundError is raised by the JVM itself when compiled code references a class that cannot load. The missing jar is often the same; the doorway differs.

The driver worked before I upgraded the database connector, why now? The upgrade renamed the driver class (MySQL's move from com.mysql.jdbc.Driver to com.mysql.cj.jdbc.Driver is the famous case). Update the configured name to match the new jar.

Do I still need Class.forName for JDBC? Usually not with current drivers, which auto-register. The call survives in old code and tutorials. Its failure is still useful: it proves the jar is missing or the name is wrong before any connection is attempted.

Related errors

NoClassDefFoundError · Could not find or load main class · UnsupportedClassVersionError