What causes and what are the differences between NoClassDefFoundError and ClassNotFoundException?

185,562

Solution 1

The difference from the Java API Specifications is as follows.

For 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.

For 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.

So, it appears that the NoClassDefFoundError occurs when the source was successfully compiled, but at runtime, the required class files were not found. This may be something that can happen in the distribution or production of JAR files, where not all the required class files were included.

As for ClassNotFoundException, it appears that it may stem from trying to make reflective calls to classes at runtime, but the classes the program is trying to call is does not exist.

The difference between the two is that one is an Error and the other is an Exception. With NoClassDefFoundError is an Error and it arises from the Java Virtual Machine having problems finding a class it expected to find. A program that was expected to work at compile-time can't run because of class files not being found, or is not the same as was produced or encountered at compile-time. This is a pretty critical error, as the program cannot be initiated by the JVM.

On the other hand, the ClassNotFoundException is an Exception, so it is somewhat expected, and is something that is recoverable. Using reflection is can be error-prone (as there is some expectations that things may not go as expected. There is no compile-time check to see that all the required classes exist, so any problems with finding the desired classes will appear at runtime.

Solution 2

A ClassNotFoundException is thrown when the reported class is not found by the ClassLoader. This typically means that the class is missing from the CLASSPATH. It could also mean that the class in question is trying to be loaded from another class which was loaded in a parent classloader and hence the class from the child classloader is not visible. This is sometimes the case when working in more complex environments like an App Server (WebSphere is infamous for such classloader issues).

People often tend to confuse java.lang.NoClassDefFoundError with java.lang.ClassNotFoundException however there's an important distinction. For example an exception (an error really since java.lang.NoClassDefFoundError is a subclass of java.lang.Error) like

java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory

does not mean that the ActiveMQConnectionFactory class is not in the CLASSPATH. Infact its quite the opposite. It means that the class ActiveMQConnectionFactory was found by the ClassLoader however when trying to load the class, it ran into an error reading the class definition. This typically happens when the class in question has static blocks or members which use a Class that's not found by the ClassLoader. So to find the culprit, view the source of the class in question (ActiveMQConnectionFactory in this case) and look for code using static blocks or static members. If you don't have access the the source, then simply decompile it using JAD.

On examining the code, say you find a line of code like below, make sure that the class SomeClass in in your CLASSPATH.

private static SomeClass foo = new SomeClass();

Tip : To find out which jar a class belongs to, you can use the web site jarFinder . This allows you to specify a class name using wildcards and it searches for the class in its database of jars. jarhoo allows you to do the same thing but its no longer free to use.

If you would like to locate the which jar a class belongs to in a local path, you can use a utility like jarscan ( http://www.inetfeedback.com/jarscan/ ). You just specify the class you'd like to locate and the root directory path where you'd like it to start searching for the class in jars and zip files.

Solution 3

NoClassDefFoundError is a linkage error basically. It occurs when you try and instantiate an object (statically with "new") and it's not found when it was during compilation.

ClassNotFoundException is more general and is a runtime exception when you try to use a class that doesn't exist. For example, you have a parameter in a function accepts an interface and someone passes in a class that implements that interface but you don't have access to the class. It also covers case of dynamic class loading, such as using loadClass() or Class.forName().

Solution 4

A NoClassDefFoundError (NCDFE) happens when your code runs "new Y()" and it can't find the Y class.

It may simply be that Y is missing from your class loader like the other comments suggest, but it could be that the Y class isn't signed or has an invalid signature, or that Y is loaded by a different classloader not visible to your code, or even that Y depends on Z which couldn't be loaded for any of the above reasons.

If this happens, then the JVM will remember the result of loading X (NCDFE) and it will simply throw a new NCDFE every time you ask for Y without telling you why:

class a {
  static class b {}
  public static void main(String args[]) {
    System.out.println("First attempt new b():");
    try {new b(); } catch(Throwable t) {t.printStackTrace();}
    System.out.println("\nSecond attempt new b():");
    try {new b(); } catch(Throwable t) {t.printStackTrace();}
  }
}

save this as a.java somewhere

The code simply tries to instantiate a new "b" class twice, other than that, it doesn't have any bugs, and it doesn't do anything.

Compile the code with javac a.java, Then run a by invoking java -cp . a -- it should just print out two lines of text, and it should run fine without errors.

Then delete the "a$b.class" file (or fill it with garbage, or copy a.class over it) to simulate the missing or corrupted class. Here's what happens:

First attempt new b():
java.lang.NoClassDefFoundError: a$b
    at a.main(a.java:5)
Caused by: java.lang.ClassNotFoundException: a$b
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
    ... 1 more

Second attempt new b():
java.lang.NoClassDefFoundError: a$b
    at a.main(a.java:7)

The first invocation results in a ClassNotFoundException (thrown by the class loader when it can't find the class), which must be wrapped in an unchecked NoClassDefFoundError, since the code in question (new b()) should just work.

The second attempt will of course fail too, but as you can see the wrapped exception is no more, because the ClassLoader seems to remember failed class loaders. You see only the NCDFE with absolutely no clue as to what really happened.

So if you ever see a NCDFE with no root cause, you need to see if you can track back to the very first time the class was loaded to find the cause of the error.

Solution 5

From http://www.javaroots.com/2013/02/classnotfoundexception-vs.html:

ClassNotFoundException : occurs when class loader could not find the required class in class path. So, basically you should check your class path and add the class in the classpath.

NoClassDefFoundError : this is more difficult to debug and find the reason. This is thrown when at compile time the required classes are present, but at run time the classes are changed or removed or class's static initializes threw exceptions. It means the class which is getting loaded is present in classpath, but one of the classes which are required by this class are either removed or failed to load by compiler. So you should see the classes which are dependent on this class.

Example:

public class Test1
{
}


public class Test 
{
   public static void main(String[] args)
   {
        Test1 = new Test1();    
   }

}

Now after compiling both the classes, if you delete Test1.class file and run Test class, it will throw

Exception in thread "main" java.lang.NoClassDefFoundError: Test
    at Test1.main(Test1.java:5)
Caused by: java.lang.ClassNotFoundException: Test
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 1 more

ClassNotFoundException: thrown when an application tries to load in a class through its name, but no definition for the class with the specified name could be found.

NoClassDefFoundError: thrown if the Java Virtual Machine tries to load in the definition of a class and no definition of the class could be found.

Share:
185,562
krisp
Author by

krisp

Am a programmer in Mumbai City. #SOreadytohelp

Updated on July 08, 2022

Comments

  • krisp
    krisp almost 2 years

    What is the difference between NoClassDefFoundError and ClassNotFoundException?

    What causes them to be thrown? How can they be resolved?

    I often encounter these throwables when modifying existing code to include new jar files. I have hit them on both the client side and the server side for a java app distributed through webstart.

    Possible reasons I have come across:

    1. packages not included in build.xml for the client side of code
    2. runtime classpath missing for the new jars we are using
    3. version conflicts with previous jar

    When I encounter these today I take a trail-and-error approach to get things working. I need more clarity and understanding.

  • user43685
    user43685 about 13 years
    It i funny that this is exactly correct answer voted the last. (Even -1 before I voted). ClassNotFoundException means the CL doesn't see .class file. NoClassDefFoundError means the .class file is there it is not loadable (possibly JNI error).
  • zardosht
    zardosht over 11 years
    Isn't this answer contradicting with answer form coobird?
  • Kaushik Lele
    Kaushik Lele over 11 years
    I tried similar example of Static block. My class Class1 has static variable "private static B foo = new B();" After compilation, I removed the B.class file from bin folder. Now from Main method of third class when I create object of Class1. The rror is thown as follws :-------- "Exception in thread "main" java.lang.NoClassDefFoundError: spring/B" ........ So it exactly mentiones which class it did not found i.e.class referred in static block and not the outer class.So it is contrary to this answer.
  • Dagang
    Dagang over 10 years
    NoClassDefFoundError usually occurs when there's problem (exception thrown) with the static block or static fields initialization of the class, so the class can't be initialized successfully.
  • Ravi
    Ravi almost 9 years
    upvote. one is an Error and the other is an Exception. :)
  • user207421
    user207421 almost 8 years
    Upvote for mentioning 'the name in the class file does not match the requested name'. This is a quite common cause.
  • PJTraill
    PJTraill almost 8 years
    What about running the JVM with -verbose, or some similar option depending on the specific JVM? Probably -verbose:class, maybe -verbose:class:jni if using JNI, but I’m not sure about the syntax.
  • PJTraill
    PJTraill almost 8 years
    What about running the JVM with -verbose, or some similar option depending on the specific JVM? Probably -verbose:class, maybe -verbose:class:jni if using JNI, but I’m not sure about the syntax. If this is useful, perhaps you could show the results.
  • mogsie
    mogsie almost 8 years
    Neither -verbose:class nor -verbose:jni give any additional output relevant to the missing class.
  • PJTraill
    PJTraill almost 8 years
    -verbose:class:jni is wrong, but you can pass two separate options: -verbose:class -verbose:jni.
  • PJTraill
    PJTraill almost 8 years
    Thanks for trying it out, even if the result is disappointing. (P.S. I have since found out that -verbose:class:jni is wrong: one has to specify two separate options: -verbose:class -verbose:jni.)
  • batwad
    batwad about 6 years
    The last sentence * 1,000,000: So if you ever see a NCDFE with no root cause, you need to see if you can track back to the very first time the class was loaded to find the cause of the error.
  • akila
    akila almost 5 years
    +1 for the clarification regarding "does not mean that the ActiveMQConnectionFactory class is not in the CLASSPATH"
  • Stephen C
    Stephen C over 4 years
    Not crystal clear. "Not updated in the classpath" is vague / imprecise. This is about the either the JAR not being present in the classpath, or the wrong version of the JAR being on the classpath. And spelling errors. And (sigh) since you posted your information as a funky graphic, we can't fix this.