ClassNotFoundException vs NoClassDefFoundError
Asked Answered
C

9

37

I have gone through this thread What causes and what are the differences between NoClassDefFoundError and ClassNotFoundException? This is what one of the ans,which has max ups, in thread is : NoClassDefFoundError :"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."

ClassNotFoundException : 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.

I did a small experiment . I created a main class, class A and tried to call other class, class B from it , compiled successfully.

Then i deleted the class B which is being called in class A. I got the java.lang.ClassNotFoundException but as per the answer in the tread, i should have got NoClassDefFoundError (source was compiled succesfully but at runtime class files were not found) Could anyone explain what am i missing in the interpretation of the ans in the thread ?

package com.random;

public class A {

    public static void main(String[] args) {
        B b= new B();

    }

}

 package com.random;

public class B {



}
Cachepot answered 4/2, 2015 at 13:38 Comment(3)
Interesting, because another site did the same test and got the result you're looking for: javaroots.com/2013/02/classnotfoundexception-vs.htmlPotbelly
I'd be curious to see what would happen if you put class B in a different package and then had to include import com.random.blah.B; in class A.Ignitron
Interesting. After deleting B.class I got this: Exception in thread "main" java.lang.NoClassDefFoundError: com/random/B at com.random.A.main(A.java:6) Caused by: java.lang.ClassNotFoundException: com.random.BObedient
A
26

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
Alfredoalfresco answered 4/2, 2015 at 13:56 Comment(1)
The stack trace erroneously complains about TestClass while it should mention Test.Kibler
C
13

Well... ClassNotFoundException occurs when the runtime is trying to find the class named by some string, for example, the Class.forName(java.lang.String) method takes a string argument and tries to find the class with this name. In this case, the class name is a String and can only be checked at runtime. Here the exception clearly says "this class is not found". So, it can happen for two reasons:

  1. The class name is not a valid java-class. Example: Class cdef = Class.forName( "java.bang.kiting" );
  2. The class name was a valid class, but somehow it was not packaged with the jar or is not resolved in the class-path. So as far as the runtime knows, it is an invalid class name. Example: Class cdef = Class.forName( "apache.some.SomeLegitClass" );

Whereas NoClassDefFoundError is thrown for cases where the actual class reference was used,

// example
import apache.some.SomeLegitClass
SomeLegitClass i = (SomeLegitClass) instanceOfSomeLegitClass;

So basically everything was correct but somehow the class is not packaged with the jar ( or, more generally, is not resolved in the class-path ). In this case we get a NoClassDefFoundError thrown.

Here the runtime knows that the class is valid since it compiled successfully but it can not find the class definition.

Codi answered 4/2, 2015 at 13:53 Comment(1)
"Here runtime knows that the class is valid since it compiled successfully... but it can not find the "class definition" - this line is the essence of this ansCachepot
C
13

The difference depends on who asked the class to be loaded:

  • ClassNotFoundException is thrown when the code is directly trying to load a class, passing the String argument representing a Fully Qualified Name of the class.
    • e.g. Class.forName(String), or ClassLoader.loadClass(String).
  • NoClassDefFoundError is thrown when the JVM is asked to load a class indirectly.
    • e.g. when class A is using class B and class B is not on classpath, NoClassDefFoundError will be thrown.
Celerity answered 4/2, 2015 at 14:0 Comment(0)
W
2

NoClassDefFoundError is usually called when you are using a library(for example, Guava, Gson, CommonsIO). You put the library in classpath of your project, but you didn't export it together, you will get a NoClassDefFoundError when the application is running.

How to get NoClassDefFoundError:
Create a new project, with this class.

public class A
{
    public void do()
    {
        System.out.println("Do!");
    }
}  

Export it as a .jarfile.

Now create another project. Add the exported jar file to classpath.

import ???.A;
public class Main
{
    public static void main(String[] args)
    {
        A a = new A();
        a.do();//NoClassDefFoundError thrown at here.
    }
} 

Export the project, make sure you do not include the jar file(with class A). Run the newly exported jar file, you will see that error!

Winch answered 4/2, 2015 at 13:51 Comment(0)
E
2

1) ClassNotFoundException

  1. This occurs, when we try to load a class at run-time using Class.forName() or ClassLoader.loadClass() or ClassLoader.findSystemClass() methods and it could not find the required class in the class path.
  2. In this case, we should check the class path and add the class in the class path if it is missing.
  3. This is a checked Exception, which is derived from java.lang.Exception class .
  4. This comes under explicit loading.

2) NoClassDefFoundError

  1. This occurs, when the class was present during the compile time and is not available during run time for some reasons. It means the class which is getting loaded is present in classpath , but one of the dependent classe(s) which are required by this class are either removed or failed to load by the compiler.

  2. In this case, we only need to check the classes which are dependent on this class.

  3. This is an Error, which is derived from java.lang.LinkageError.
  4. This comes under implicit loading.
Epa answered 18/10, 2016 at 12:57 Comment(1)
It always confuses. In given example in question class B is indirectly referred by class A. class A depends on class B, so it should throw NoClassDefFoundError.Brassbound
M
2

Everything About ClassNotFoundException Vs NoClassDefFoundError article explains the difference between ClassNotFoundException Vs NoClassDefFoundError very clearly with example and according to it.

ClassNotFoundException Vs NoClassDefFoundError -- Programming Mitra

ClassNotFoundException

Is a checked exception that occurs when we tell JVM to load a class by its string name using Class.forName() or ClassLoader.findSystemClass() or ClassLoader.loadClass() methods and mentioned class is not found in the classpath.

Most of the time, this exception occurs when you try to run an application without updating the classpath with required JAR files. For Example, You may have seen this exception when doing the JDBC code to connect to your database i.e.MySQL but your classpath does not have the jar for it.

public class Test {
    public static void main(String[] args) throws Exception {

        // Provide any class name to Class.forName() which does not exist
        // Or compile Test.java and then manually delete Person.class file so Person class will become unavailable
        // Run the program using java Test

        Class clazz = Class.forName("Person");
        Person person = (Person) clazz.newInstance();
        person.saySomething();
    }
}

class Person {
    void saySomething() {
        System.out.println("Hello");
    }
}

NoClassDefFoundError

Is a subtype of java.lang.Error and Error class indicates an abnormal behavior which really should not happen with an application but and application developers should not try to catch it, it is there for JVM use only.

NoClassDefFoundError occurs when JVM tries to load a particular class that is the part of your code execution (as part of a normal method call or as part of creating an instance using the new keyword) and that class is not present in your classpath but was present at compile time because in order to execute your program you need to compile it and if you are trying use a class which is not present compiler will raise compilation error.

public class Test {
    public static void main(String[] args) throws Exception {

        // Do javac on Test.java, 
        // Program will compile successfully because Empoyee class exits
        // Manually delete Employee.class file
        // Run the program using java Test
        Employee emp = new Employee();
        emp.saySomething();

    }
}

class Employee {
    void saySomething() {
        System.out.println("Hello");
    }
}
Manager answered 20/1, 2018 at 7:46 Comment(0)
G
1

As mentioned in previous answers, NoClassDefFoundError will occur when the class was present during the compile time and is not available during run time for some reasons.

There is another scenario I wish to add, which could also result in NoClassDefFoundError.

When you are trying to load a class which failed to load due to some exception say failure in static initialization block, system will throw you ExceptionInInitializerError. If you try to load the same class again (which failed to load previously), system will throw NoClassDefFoundError

Lets explore it with an sample

ClassWithStaticBlock.java

public class ClassWithStaticBlock {

    static {
       int total = 1/0;
    }
}

Main.java

public class Main {

public static void main(String[] args) {
    ClassWithStaticBlock cs;
    try {
       cs = new ClassWithStaticBlock();
    }catch(Throwable e){
        e.printStackTrace();
    }
  }
}

Result:

java.lang.ExceptionInInitializerError
    at Main.main(Main.java:6)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ArithmeticException: / by zero
    at ClassWithStaticBlock.<clinit>(ClassWithStaticBlock.java:7)
    ... 6 more

Lets modify Main.java

public class Main {

    public static void main(String[] args) {
        ClassWithStaticBlock cs;
        try {
           cs = new ClassWithStaticBlock();
        }catch(Throwable e){
            e.printStackTrace();
        }
        cs = new ClassWithStaticBlock(); //try to use ClassWithStaticBlock again
    }
}

Result:

java.lang.ExceptionInInitializerError
    at Main.main(Main.java:6)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ArithmeticException: / by zero
    at ClassWithStaticBlock.<clinit>(ClassWithStaticBlock.java:7)
    ... 6 more
Exception in thread "Main Thread" java.lang.NoClassDefFoundError: ClassWithStaticBlock
    at Main.main(Main.java:10)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

When we try to use ClassWithStaticBlock again (which failed to initialize earlier), System is throwing NoClassDefFoundError.

Found the sample from Why am I getting a NoClassDefFoundError in Java?

Germicide answered 27/12, 2016 at 11:31 Comment(0)
S
0

One of cases where NoClassDefFoundError occur is when the Class JVM is trying to access is not found in classpath. But if class is present in classpath, It will result in ClassNotFoundException.

In short NoClassDefFoundError will come if a class was present during compile time but not available in java classpath during runtime.

Just try to run with explicit -classpath option where the classpath does not contain class B.

Selfanalysis answered 4/2, 2015 at 13:59 Comment(1)
Why would you get a ClassNotFoundException if the class is present in the classpath?Irrefutable
S
-2

The other answers in this thread are correct, i just want to add something i spent hours trying to figure out. Even if

Class.forName("apache.some.SomeLegitClass")

works,

Class.forName("apache.some.somelegitclass")

will result in a NoClassDefFoundError. The Class.forName() is case-sensitive. It will result in different exceptions if the classname is spelled wrong, or simply has incorrect casing.

Slipcover answered 5/7, 2016 at 13:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.