Java "java.lang.ClassNotFoundException" at Runtime - Fix Classpath in CI
The JVM tried to load a class by name at runtime and could not find its .class file anywhere on the classpath. It compiled because the type was visible then, but the artifact that contains it is absent when the program actually runs.
What this error means
A run or test throws java.lang.ClassNotFoundException: com.example.Foo, usually from Class.forName, a service loader, or a reflective lookup. Compilation passed; the failure only appears when the class is loaded.
Exception in thread "main" java.lang.ClassNotFoundException: com.example.driver.PgDriver
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at com.example.App.main(App.java:18)Common causes
A runtime dependency is missing from the classpath
A library used only via reflection (JDBC drivers, SPI providers) is declared provided/compileOnly, or not declared at all, so it is not present when the JVM resolves the name.
A fat jar or test classpath dropped the class
A shaded/assembly build excluded the package, or the test runtime classpath differs from compile, so the loader has no .class for that name.
How to fix it
Declare the dependency with runtime scope
Add the artifact that contains the class so it ships on the runtime classpath, not just at compile time.
<!-- Maven: runtime so the driver is on the run/test classpath -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.3</version>
<scope>runtime</scope>
</dependency>Inspect what is actually on the classpath
- Run
mvn dependency:tree(orgradle dependencies) and confirm the artifact appears in the runtime/test configuration. - For a fat jar, list its contents (
jar tf app.jar | grep Foo) to verify the class was packaged. - Check that the class is not declared
providedorcompileOnlywhen it is needed at runtime.
How to prevent it
- Use
runtimescope for reflection-only libraries (JDBC, SPI), and assert the packaged jar contains required classes in CI before publishing.