Why am I getting a NoClassDefFoundError in Java?
This is caused when there is a class file that your code depends on and it is present at compile time but not found at runtime. Look for differences in your build time and runtime classpaths.
How can I solve java.lang.NoClassDefFoundError?
After you compile your code, you end up with .class
files for each class in your program. These binary files are the bytecode that Java interprets to execute your program. The NoClassDefFoundError
indicates that the classloader (in this case java.net.URLClassLoader
), which is responsible for dynamically loading classes, cannot find the .class
file for the class that you're trying to use.
Your code wouldn't compile if the required classes weren't present (unless classes are loaded with reflection), so usually this exception means that your classpath doesn't include the required classes. Remember that the classloader (specifically java.net.URLClassLoader
) will look for classes in package a.b.c in folder a/b/c/ in each entry in your classpath. NoClassDefFoundError
can also indicate that you're missing a transitive dependency of a .jar file that you've compiled against and you're trying to use.
For example, if you had a class com.example.Foo
, after compiling you would have a class file Foo.class
. Say for example your working directory is .../project/
. That class file must be placed in .../project/com/example
, and you would set your classpath to .../project/
.
Side note: I would recommend taking advantage of the amazing tooling that exists for Java and JVM languages. Modern IDEs like Eclipse and IntelliJ IDEA and build management tools like Maven or Gradle will help you not have to worry about classpaths (as much) and focus on the code! That said, this link explains how to set the classpath when you execute on the command line.
Why am I getting a NoClassDefFoundError exception rather than a StackOverflow error?
This is not a bug and it also has nothing to do with static methods in interfaces.
The java.lang.instrument ASSERTION FAILED
message is also not relevant and is just an artifact of running the code from IDE. Running the same class from the command line will result in Exception in thread "main"
only.
Lets simplify your example to
public class Test {
public static void main( String[] args ) throws Exception {
recursive();
}
public static void recursive() throws Exception {
try {
Test.class
.getDeclaredMethod( "recursive" )
.invoke( null );
} catch ( InvocationTargetException e ) {
e.printStackTrace();
}
}
}
What is going on:
- The recursive method causes
StackOverflowError
, as expected. - The
StackOverflowError
is wrapped intoInvocationTargetException
which is thrown from the deepest nested call tomethod.invoke()
. - The
InvocationTargetException
is immediately caught and JVM tries to executeprintStackTrace()
but in order to do that it needs to load some classes. But remember that at this point the stack is depleted and any non-trivial methods will hitStackOverflowError
again, which is exactly what happens somewhere inside the class loader when it tries to load some class required to print a stack trace. The class loader did found the class, but failed to load and initialize it, and it reports that asNoClassDefFoundError
.
The following code will prove that InvocationTargetException
indeed wraps StackOverflowError
:
public class Test {
public static void main( String[] args ) throws Exception {
recursive();
}
public static void recursive() throws Exception {
try {
Test.class
.getDeclaredMethod( "recursive" )
.invoke( null );
} catch ( InvocationTargetException e ) {
System.out.println(e);
System.out.println(e.getTargetException());
}
}
}
And the following code will prove that if classes required to execute printStackTrace()
are already loaded, then the code behaves as expected (prints a stack trace for InvocationTargetException
caused by StackOverflowError
:
public class Test {
public static void main( String[] args ) throws Exception {
new Exception().printStackTrace(); // initialize all required classes
recursive();
}
public static void recursive() throws Exception {
try {
Test.class
.getDeclaredMethod( "recursive" )
.invoke( null );
} catch ( InvocationTargetException e ) {
e.printStackTrace();
}
}
}
The open question is why reflection API handlesStackOverflowError
at all, instead of simply terminating the whole call chain with the error.
ClassNotFoundException vs NoClassDefFoundError
NoClassDefFoundError
Thrown if the Java Virtual Machine or a ClassLoader instance tries to
load in the definition of a class (as part of a normal method call or
as part of creating a new instance using the new expression) and no
definition of the class could be found.The searched-for class definition existed when the currently executing
class was compiled, but the definition can no longer be found.
ClassNotFoundException
Thrown when an application tries to load in a class through its string
name using: The forName method in class Class. The findSystemClass
method in class ClassLoader . The loadClass method in class
ClassLoader.
You have to understand that the JVM
can't realize the definition of the class
you deleted can't be found, as the class
itself can't be found which automatically throw the ClassNotFoundException
.
This exception happen at runtime
so it does not matter if it compiled first or not, you deleted the file, therefore it can't be found and throw the exception
.
Note that NoClassDefFoundError
is not actually an exception, it is an Error
derived from LinkageError
while ClassNotFoundException
derive directly from java.lang.Exception
.
To resume, the NoClassDefFoundError
globally simply mean that the JVM
tried to access at runtime
something that according to the compiled
code should exists, but does not actually exist (or is not in the classpath).
Example to reproduce ClassNotFoundException
public class ClassNotFoundExceptionExample {
private static final String CLASS_TO_LOAD = "main.java.Utils";
public static void main(String[] args) {
try {
Class loadedClass = Class.forName(CLASS_TO_LOAD);
System.out.println("Class " + loadedClass + " found successfully!");
}
catch (ClassNotFoundException ex) {
System.err.println("A ClassNotFoundException was caught: " + ex.getMessage());
ex.printStackTrace();
}
}
}
Example to reproduce NoClassDefFoundError
Create a simple class Test
public class Test {
public Test() {
System.out.println("A new instance of the Test class was created!");
}
}
And a class NoClassDefFoundErrorExample
public class NoClassDefFoundErrorExample {
private static Test test = new Test();
public static void main(String[] args) {
System.out.println("The definition of Test was found!");
}
}
Now create a n executable .jar
which execute the main
method. You can specify it in the Manifest.txt
file inside the .jar
Main-Class: NoClassDefFoundErrorExample
Now run the following commands
javac Test.java
javac NoClassDefFoundErrorExample.java
jar cfm NoClassDefFoundErrorExample.jar Manifest.txt NoClassDefFoundErrorExample.class
java -jar NoClassDefFoundErrorExample.jar
Notice the NoClassDefFoundError
Exception in thread "main" java.lang.NoClassDefFoundError: TestClass
at NoClassDefFoundErrorExample.(NoClassDefFoundErrorExample.java:2)
Caused by: java.lang.ClassNotFoundException: TestClass
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
How do I resolve ClassNotFoundException?
Your classpath is broken (which is a very common problem in the Java world).
Depending on how you start your application, you need to revise the argument to -cp
, your Class-Path entry in MANIFEST.MF or your disk layout.
Handle a NoClassDefFoundError?
I dont need to fix the missing classes because this is part of my program.
I am not completely sure what you are trying to achieve here but you should be able to catch
a NoClassDefFoundError
to prevent your JVM from crashing. Let A
be a class that has-a reference to B
. If B.class
is not available at runtime, you can handle the NoClassDefFoundError
as follows :
class C {
public static void main(String args[]) {
try {
A a = new A();
} catch (NoClassDefFoundError e) {
//log the error or take some action
}
System.out.println("All good here, lets continue");
}
}
What could cause a NoClassDefFoundError on one specific system only?
In my case, since I had set a timeout of 1,500 milliseconds on the future and because of the slower CPU clock speed of the misbehaving machine, the class was not fully initialised when the timeout occurred. Turns out, OkHttp is more or less the culprit, it takes more than 5 seconds to inistalise the client on the given machine.
All in all, I am no longer applying any timeout on the first try of the connection test to give OkHttp enough time to initialise itself.
Note that this would not solve the problem if the initialisation of the HTTPClient
was to fail at a different point in the application lifecycle. But since the first try of the connection test is the first place to call into HTTPClient
, this is the only place where it can be initialised.
Related Topics
Parsing Query Strings on Android
Do Line Endings Differ Between Windows and Linux
What Is a Stack Trace, and How to Use It to Debug My Application Errors
How to Append Text to an Existing File in Java
How Do the Post Increment (I++) and Pre Increment (++I) Operators Work in Java
What Are the Possible Values of the Hibernate Hbm2Ddl.Auto Configuration and What Do They Do
How to Increment a Date by One Day in Java
Do Java Arrays Have a Maximum Size
How to Print a Query String With Parameter Values When Using Hibernate
Android on Text Change Listener
Javafx on Linux Is Showing a "Graphics Device Initialization Failed For: Es2, Sw"
How to Use Java.Util.Scanner to Correctly Read User Input from System.In and Act on It
What's Wrong With Java Date & Time API