NoClassDefFoundError vs ClassNotFoundException
Let us go through the definitions of the above throwables from the java doc
java.lang.NoClassDefFoundError
Thrown if the Java Virtual Machine or a classloader 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.
java.lang.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.
but no definition for the class with the specified name could be found.
Here the most important part is that the error java.lang.NoClassDefFoundError is thrown when a class is not found in the class path at runtime but the class was present at the time of compilation.
While the exception java.lang.ClassNotFoundException is thrown by the methods which tries to load the class at runtime but the class is not required to be present in the classpath at compile time.
Let me explain the above using an example. Let us consider following class:
MyPrint.java
package test;
public class MyPrint
{
public void print(String str)
{
System.out.println(str);
}
}
The method "print" is called from a class Test
Test.java
import test.MyPrint;class Test
{
public static void main(String[] args)
{
MyPrint mp = new MyPrint();
mp.print("Class is loaded");
}
}
Here to compile the Test.java file you have to make sure that MyPrint.class is there in the classpath.
Now if you remove the MyPrint.class from the classpath (after compilation) and try to run “java Test” you’ll receive following error:
Exception in thread "main" java.lang.NoClassDefFoundError: test/MyPrint
at Test.main(Test.java:7)
Let us modify the Test.java file a bit:
//No Import requiredPlease note the changes. Here we are using reflection to call the method. At the time of compilation you don’t need MyPrint.class to be present in the classpath. Also as because “Class.forName” method throws java.lang.ClassNotFoundException (which is not error), you need to catch the exception. Here we have just re-thrown the exception.
//import test.MyPrint;
import java.lang.reflect.Method;
class Test
{
public static void main(String[] args) throws Exception
{
Class cls = Class.forName("test.MyPrint");
Method meth = cls.getMethod("print", new Class[]{String.class});
meth.invoke(cls.newInstance(), new Object[]{"Class is loaded"});
}
}
Run if you run “java Test”, following exception will be thrown:
Exception in thread "main" java.lang.ClassNotFoundException: test.MyPrint
Now people who have worked with application servers (or even web servers) must have seen java.lang.ClassNotFoundException often. There your servlets, bean class etc are specified in the descriptors (mainly XML files). So the application class loader reads the descriptor and tries to load the classes. In case the class loader fails to load the class, the exception java.lang.ClassNotFoundException is thrown. You’ll find same exception often while working on JDBC, Spring etc in which involves similar situation.
Resolution (in general):
java.lang.NoClassDefFoundError
- Make sure the class is there in the classpath.
java.lang.ClassNotFoundException
- Make sure the class is there in the classpath.
- Make sure your configuration files (specially where you are specifying the classes) are proper.
In case you have multiple class loaders you need to keep in mind that classes loaded by child class loader can't be seen by parent class loaders.
No comments:
Post a Comment