web-dev-qa-db-fra.com

ClassNotFoundException vs NoClassDefFoundError

J'ai traversé ce fil Quelles sont les causes et quelles sont les différences entre NoClassDefFoundError et ClassNotFoundException? Voici ce que l’un des ans, qui a max ups, dans le fil est: NoClassDefFoundError: "Il semble donc que NoClassDefFoundError se produise lorsque la source a été compilée avec succès, mais au moment de l'exécution, les fichiers de classe requis étaient introuvables. Cela peut se produire lors de la distribution ou de la production de fichiers JAR, où tous les fichiers de classe requis n'étaient pas inclus. "

ClassNotFoundException: comme pour ClassNotFoundException, il semble que cela puisse provenir de la tentative d'appels réflexifs aux classes au moment de l'exécution, mais que les classes que le programme tente d'appeler n'existent pas.

J'ai fait une petite expérience. J'ai créé une classe principale, class A et essayé d'appeler une autre classe, la classe B, compilée avec succès.

Ensuite, j'ai supprimé la classe B qui est appelée dans la classe A . J'ai eu la Java.lang.ClassNotFoundException mais comme le dit la réponse dans la foulée, j'aurais dû avoir NoClassDefFoundError (la source a été compilée avec succès les fichiers de classe d'exécution n'ont pas été trouvés) Quelqu'un pourrait-il expliquer ce qui me manque dans l'interprétation des années dans le fil de discussion?

package com.random;

public class A {

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

    }

}

 package com.random;

public class B {



}
18
Deen John

NoClassDefFoundError

Émis si la machine virtuelle Java ou une instance de ClassLoader essaie de charger dans la définition d'une classe (dans le cadre d'un appel de méthode normal ou dans le cadre de la création d'une nouvelle instance à l'aide de la nouvelle expression) et no définition de la classe pourrait être trouvé.

La définition de classe recherchée existait lors de l'exécution de La classe a été compilée, mais la définition est introuvable.


ClassNotFoundException

Lancé lorsqu'une application tente de charger une classe via sa chaîne name using: La méthode forName dans la classe Class. La classe findSystem method dans la classe ClassLoader. La méthode loadClass dans la classe ClassLoader.


Vous devez comprendre que la JVM ne peut pas réaliser la définition de la class que vous avez supprimée est introuvable, car la class elle-même ne peut pas être trouvée et jette automatiquement la ClassNotFoundException.

Cette exception se produisant à runtime, peu importe si elle a été compilée en premier ou non, vous avez supprimé le fichier. Par conséquent, il est introuvable et lancez la variable exception.

Notez que NoClassDefFoundError n'est pas réellement une exception, c'est une Error dérivée de LinkageError tandis que ClassNotFoundException dérive directement de Java.lang.Exception.

Pour résumer, NoClassDefFoundError signifie globalement simplement que JVM a essayé d'accéder à runtime quelque chose qui, selon le code compiled, devrait exister, mais n'existe pas réellement (ou n'est pas dans le chemin de classe).


Exemple de reproduction de 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();
        }
    }
}

Exemple de reproduction de NoClassDefFoundError

Créer une classe simple Test 

public class Test {
        public Test() {
                System.out.println("A new instance of the Test class was created!");
        }
}

Et une classe 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!");
        }
}

Créez maintenant un n exécutable .jar qui exécute la méthode main. Vous pouvez le spécifier dans le fichier Manifest.txt à l'intérieur du .jar

Main-Class: NoClassDefFoundErrorExample

Maintenant, lancez les commandes suivantes

javac Test.Java
javac NoClassDefFoundErrorExample.Java
jar cfm NoClassDefFoundErrorExample.jar Manifest.txt NoClassDefFoundErrorExample.class
Java -jar NoClassDefFoundErrorExample.jar

Remarquez la 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
10

Eh bien ... ClassNotFoundException se produit lorsque le moteur d’exécution tente de trouver la classe nommée par une méthode String; par exemple, la méthode Class.forName(Java.lang.String) prend un argument de chaîne et essaie de trouver la classe portant ce nom. Dans ce cas, le nom de la classe est une piqûre et ne peut être vérifié qu'au moment de l'exécution. ici l'exception dit clairement ... cette "classe" est introuvable. Donc ... cela peut arriver pour deux raisons:

Raison 1. Le nom de la classe n'est pas une classe Java valide (exemple - "Java.bang.kiting").

// Example    
Class cdef = Class.forName( "Java.bang.kiting" );

Raison 2. Le nom de la classe était une classe valide ... mais il n'a pas été emballé avec le fichier jar ou n'a pas été résolu dans le chemin de la classe. Donc, autant que le runtime le sache ... il peut s'agir d'un nom de classe erroné ... semblable au cas 1.

// Example    
Class cdef =Class.forName( "Apache.some.SomeLegitClass" );

NoClassDefFoundError pour les cas où la référence de classe réelle a été utilisée,

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

Donc fondamentalement, tout était correct mais d'une manière ou d'une autre, la classe n'est pas packagée avec le fichier jar (ou plus généralement - n'est pas résolue dans le chemin de classe). Dans ce cas, nous obtenons NoClassDefFoundError.

Ici, le moteur d'exécution sait que la classe est valide car il a été compilé avec succès ... mais il ne peut pas trouver la "définition de classe".

9
Sarvesh Kumar Singh

La différence dépend de qui a demandé à la classe d'être chargée :

  • ClassNotFoundException est lancé lorsque le code tente directement de charger une classe , en passant l'argument String représentant un nom complet de la classe .
    • par exemple. Class.forName(String) ou ClassLoader.loadClass(String).
  • NoClassDefFoundError est renvoyé lorsqu'il est demandé à la JVM de charger une classe indirectement .
    • par exemple. Lorsque la classe A utilise la classe B et que la classe B n'est pas sur classpath, NoClassDefFoundError sera lancé.
6
Crazyjavahacking

NoClassDefFoundError est généralement appelé lorsque vous utilisez une bibliothèque (par exemple, Guava, Gson, CommonsIO). Vous avez placé la bibliothèque dans le chemin de classe de votre projet, mais vous ne l'avez pas exportée ensemble. Vous obtiendrez une NoClassDefFoundError lorsque l'application est en cours d'exécution.

Comment obtenir NoClassDefFoundError:
Créez un nouveau projet avec cette classe.

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

Exportez-le en tant que .jarfile.

Maintenant, créez un autre projet. Ajoutez le fichier JAR exporté au classpath. 

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

Exportez le projet en veillant à ne pas inclure le fichier jar (avec la classe A). Exécutez le fichier JAR nouvellement exporté, vous verrez cette erreur!

2
Jeremy

Comme mentionné dans les réponses précédentes, NoClassDefFoundError se produira lorsque la classe était présente au moment de la compilation et n'est pas disponible au moment de l'exécution pour certaines raisons.

Je souhaite ajouter un autre scénario, qui pourrait également entraîner NoClassDefFoundError.

Lorsque vous essayez de charger une classe dont le chargement a échoué en raison d'une exception, par exemple un échec dans un bloc d'initialisation statique, le système vous lève ExceptionInInitializerError. Si vous essayez de charger à nouveau la même classe (qui avait échoué auparavant), le système lancera NoClassDefFoundError

Permet de l'explorer avec un échantillon

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();
    }
  }
}

Résultat:

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

Permet de modifier 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
    }
}

Résultat:

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)

Lorsque nous essayons d'utiliser ClassWithStaticBlock à nouveau (ce qui a échoué à initialiser plus tôt), le système lance NoClassDefFoundError.

J'ai trouvé l'échantillon depuis Pourquoi ai-je un message d'erreur NoClassDefFoundError en Java?

1
IamVickyAV

1) _ {ClassNotFoundException} _

  1. Cela se produit lorsque nous essayons de charger une classe au moment de l'exécution à l'aide des méthodes Class.forName() ou ClassLoader.loadClass() ou ClassLoader.findSystemClass() et qu'il soit non trouver la classe requise dans le chemin d'accès aux classes
  2. Dans ce cas, nous devrions vérifier le class path et ajouter la classe dans le chemin de la classe s'il en manque.
  3. Il s'agit d'une exception vérifiée, dérivée de la classe Java.lang.Exception.
  4. Cela relève de explicite chargement. 

2)NoClassDefFoundError 

  1. Cela se produit lorsque la classe était présente pendant le compile time et n'est pas disponible pendant le run time pour certaines raisons. Cela signifie que la classe en cours de chargement est present dans classpath, mais que l'un des classe(s) dépendants requis par cette classe soit supprimé ou échoué à charger par le compilateur.

  2. Dans ce cas, il suffit de vérifier le classes which are dependent on this class.

  3. Il s'agit d'une erreur, dérivée de Java.lang.LinkageError.
  4. Cela relève de implicite chargement.
1
Rohit Gaikwad

Tout à propos de ClassNotFoundException contre NoClassDefFoundError article explique très clairement la différence entre ClassNotFoundException et NoClassDefFoundError avec des exemples et en fonction des exemples.

 ClassNotFoundException Vs NoClassDefFoundError -- Programming Mitra

ClassNotFoundException

Exception vérifiée qui se produit lorsque nous indiquons à JVM de charger une classe par son nom de chaîne à l'aide de méthodes Class.forName () ou ClassLoader.findSystemClass () ou ClassLoader.loadClass () et que la classe mentionnée est introuvable dans le chemin d'accès aux classes.

La plupart du temps, cette exception se produit lorsque vous essayez d'exécuter une application sans mettre à jour le chemin d'accès aux classes avec les fichiers JAR requis. Par exemple, vous avez peut-être vu cette exception lorsque vous avez utilisé le code JDBC pour vous connecter à votre base de données i.e.MySQL, mais votre chemin d'accès aux classes ne contient pas le fichier jar correspondant.

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

Est un sous-type de Java.lang.Error et la classe Error indique un comportement anormal qui ne devrait vraiment pas se produire avec une application, mais les développeurs d’applications ne devraient pas essayer de l’attraper, c’est là uniquement pour une utilisation JVM.

NoClassDefFoundError se produit lorsque la machine virtuelle Java tente de charger une classe particulière faisant partie de l'exécution de votre code (dans le cadre d'un appel de méthode normal ou de la création d'une instance à l'aide du nouveau mot clé) et que cette classe n'est pas présente dans votre chemin d'accès aux classes, mais qu'elle était présente. au moment de la compilation, car pour exécuter votre programme, vous devez le compiler. Si vous essayez d’utiliser une classe qui n’est pas présente, le compilateur générera une erreur de compilation.

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");
    }
}
0
Naresh Joshi

ClassNotFoundException et NoClassDefFoundError se produisent lorsqu'une classe particulière est introuvable à l'exécution. Cependant, elles se produisent dans différents scénarios.

ClassNotFoundException est une exception qui se produit lorsque vous essayez de charger une classe au moment de l'exécution à l'aide des méthodes Class.forName () ou loadClass () et que les classes mentionnées ne sont pas trouvées dans le chemin d'accès aux classes.

public class MainClass
{
    public static void main(String[] args)
    {
        try
        {
            Class.forName("Oracle.jdbc.driver.OracleDriver");
        }catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }
}



Java.lang.ClassNotFoundException: Oracle.jdbc.driver.OracleDriver
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)
at Java.lang.Class.forName0(Native Method)
at Java.lang.Class.forName(Unknown Source)
at pack1.MainClass.main(MainClass.Java:17)

NoClassDefFoundError est une erreur qui se produit lorsqu'une classe particulière est présente au moment de la compilation mais manquait au moment de l'exécution.

class A
{
  // some code
}
public class B
{
    public static void main(String[] args)
    {
        A a = new A();
    }
}

Lorsque vous compilez le programme ci-dessus, deux fichiers .class seront générés. L'un est A.class et l'autre est B.class. Si vous supprimez le fichier A.class et exécutez le fichier B.class, Java Runtime System lancera NoClassDefFoundError comme ci-dessous:

Exception in thread "main" Java.lang.NoClassDefFoundError: A
at MainClass.main(MainClass.Java:10)
Caused by: Java.lang.ClassNotFoundException: A
at Java.net.URLClassLoader.findClass(URLClassLoader.Java:381)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:424)
at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:331)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
0
Neeraj Gahlawat

L'un des cas où NoClassDefFoundError se produit est lorsque la JVM de classe tente d'accéder n'est pas trouvé dans classpath . Mais si class est présent dans classpath, cela se traduira par ClassNotFoundException.

En bref, NoClassDefFoundError viendra si une classe était présente au moment de la compilation mais n'était pas disponible dans le chemin de classes Java lors de l'exécution. 

Essayez simplement de vous lancer avec l'option -classpath explicite, où classpath ne contient pas la classe B.

0
Ajit Lakhwani