web-dev-qa-db-fra.com

Quelles sont les causes et quelles sont les différences entre NoClassDefFoundError et ClassNotFoundException?

Quelle est la différence entre NoClassDefFoundError et ClassNotFoundException?

Qu'est-ce qui les cause? Comment peuvent-ils être résolus?

Je rencontre souvent ces problèmes lors de la modification de code existant pour inclure de nouveaux fichiers jar. Je les ai frappés à la fois du côté client et du côté serveur pour une application Java distribuée via Webstart.

Les raisons possibles que j'ai rencontrées:

  1. packages non inclus dans build.xml pour le côté client du code
  2. classpath d'exécution manquant pour les nouveaux bocaux que nous utilisons
  3. la version est en conflit avec la jarre précédente

Quand je rencontre ces problèmes aujourd'hui, je prends une approche de piste et d'erreur pour que les choses fonctionnent. J'ai besoin de plus de clarté et de compréhension.

361
krisp

La différence par rapport aux Java Spécifications de l'API est la suivante.

Pour ClassNotFoundException :

Lancé lorsqu'une application tente de charger une classe via son nom de chaîne en utilisant:

  • La méthode forName dans la classe Class.
  • La méthode findSystemClass dans la classe ClassLoader.
  • La méthode loadClass dans la classe ClassLoader.

mais aucune définition de la classe avec le nom spécifié n'a pu être trouvée.

Pour NoClassDefFoundError :

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

La définition de classe recherchée existait lors de la compilation de la classe en cours d'exécution, mais la définition est introuvable.

Donc, il semble que NoClassDefFoundError se produise lorsque la source a été compilée avec succès, mais au moment de l'exécution, les fichiers class requis étaient introuvables. Cela peut être quelque chose qui peut arriver dans la distribution ou la production de fichiers JAR, où tous les fichiers class requis n'ont pas été inclus.

En ce qui concerne ClassNotFoundException, il semble que cela puisse provenir d’essayer d’appeler des classes par réflexion lors de l’exécution, mais les classes que le programme tente d’appeler n’existent pas.

La différence entre les deux est que l’un est un Error et que l’autre est un Exception. NoClassDefFoundError est un Error et résulte du fait que la machine virtuelle Java a des difficultés à trouver une classe qu'elle est supposée trouver. Un programme qui devait fonctionner au moment de la compilation ne peut pas s'exécuter car les fichiers class n'ont pas été trouvés ou ne sont pas identiques à ceux produits ou rencontrés au moment de la compilation. C'est une erreur assez critique, car le programme ne peut pas être lancé par la JVM.

D'autre part, le ClassNotFoundException est un Exception, donc il est quelque peu attendu, et est quelque chose qui est récupérable. L’utilisation de la réflexion peut être source d’erreurs (certaines attentes étant que les choses ne se déroulent pas comme prévu. Aucune vérification de la compilation n’est vérifiée pour vérifier que toutes les classes requises existent, de sorte que tout problème de recherche des classes souhaitées apparaîtra au moment de l’exécution. .

382
coobird

Une exception ClassNotFoundException est levée lorsque la classe rapportée n'est pas trouvée par le chargeur de classe. Cela signifie généralement que la classe est manquante dans CLASSPATH. Cela peut également signifier que la classe en question essaie d'être chargée à partir d'une autre classe chargée dans un chargeur de classe parent. Par conséquent, la classe du chargeur de classe enfant n'est pas visible. C'est parfois le cas lorsque vous travaillez dans des environnements plus complexes tels qu'un serveur d'applications (WebSphere est célèbre pour de tels problèmes de chargeur de classes).

Les gens ont souvent tendance à confondre Java.lang.NoClassDefFoundError avec Java.lang.ClassNotFoundException mais il existe une distinction importante. Par exemple une exception (une erreur car Java.lang.NoClassDefFoundError est une sous-classe de Java.lang.Error) comme

Java.lang.NoClassDefFoundError:
org/Apache/activemq/ActiveMQConnectionFactory

ne signifie pas que la classe ActiveMQConnectionFactory n'est pas dans CLASSPATH. Enfait c'est tout le contraire. Cela signifie que le classLoader a trouvé la classe ActiveMQConnectionFactory. Toutefois, lors de la tentative de chargement de la classe, une erreur s'est produite lors de la lecture de la définition de la classe. Cela se produit généralement lorsque la classe en question a des blocs statiques ou des membres qui utilisent une classe qui n'a pas été trouvée par le chargeur de classe. Donc, pour trouver le coupable, affichez le source de la classe en question (ActiveMQConnectionFactory dans ce cas) et recherchez du code utilisant des blocs statiques ou des membres statiques. Si vous n'avez pas accès à la source, décompilez-la simplement avec JAD.

En examinant le code, supposons que vous trouviez une ligne de code comme ci-dessous, assurez-vous que la classe SomeClass est dans votre CLASSPATH.

private static SomeClass foo = new SomeClass();

Conseil: pour savoir à quel jar appartient une classe, vous pouvez utiliser le site Web jarFinder. Cela vous permet de spécifier un nom de classe à l'aide de caractères génériques et la recherche dans la base de données de fichiers jars. jarhoo vous permet de faire la même chose mais son utilisation n’est plus libre.

Si vous souhaitez localiser le fichier auquel une classe appartient dans un chemin local, vous pouvez utiliser un utilitaire tel que jarscan ( http://www.inetfeedback.com/jarscan/ ). Vous spécifiez simplement la classe que vous souhaitez localiser et le chemin du répertoire racine où vous souhaitez qu'elle commence à rechercher la classe dans les fichiers JAR et Zip.

81
Sanjiv Jivan

NoClassDefFoundError est une erreur de liaison essentiellement. Cela se produit lorsque vous essayez d'instancier un objet (de manière statique avec "nouveau") et qu'il n'a pas été trouvé lors de la compilation.

ClassNotFoundException est plus général et constitue une exception d'exécution lorsque vous essayez d'utiliser une classe qui n'existe pas. Par exemple, vous avez un paramètre dans une fonction qui accepte une interface et quelqu'un passe dans une classe qui implémente cette interface, mais vous n'avez pas accès à la classe. Il couvre également le cas du chargement dynamique de classe, comme l'utilisation de loadClass() ou Class.forName().

35
cletus

Une erreur NoClassDefFoundError (NCDFE) se produit lorsque votre code exécute "new Y ()" et qu'il ne peut pas trouver la classe Y.

Il se peut simplement que Y soit absent de votre chargeur de classes, comme le suggèrent les autres commentaires, mais il se peut également que la classe Y ne soit pas signée ou qu'elle porte une signature non valide, ou que Y soit chargé par un autre chargeur de classe non visible par votre code. , ou même que Y dépend de Z qui n’a pu être chargé pour l’une des raisons ci-dessus.

Si cela se produit, la JVM se souviendra du résultat du chargement de X (NCDFE) et lancera simplement un nouveau NCDFE à chaque fois que vous demandez Y sans vous dire pourquoi:

 class a {
 statique class b {} 
 public static void main (String args []) {
 System.out.println ("Première tentative nouveau b (): "); 
 try {new b (); } catch (Throwable t) {t.printStackTrace ();} 
 System.out.println ("\ nDécédent de la nouvelle tentative b ():"); 
 try {new b (); } catch (Throwable t) {t.printStackTrace ();} 
} 
} 

enregistrer ceci en tant que .Java quelque part

Le code essaie simplement d'instancier une nouvelle classe "b" deux fois, à part ça, il n'a pas de bugs et ne fait rien.

Compilez le code avec javac a.Java, puis exécutez a en invoquant Java -cp . a - il devrait simplement imprimer deux lignes de texte et fonctionner correctement, sans erreur.

Supprimez ensuite le fichier "a $ b.class" (ou remplissez-le de mémoire ou copiez-le a.class dessus) pour simuler la classe manquante ou corrompue. Voici ce qui se passe:

 Première tentative nouvelle b (): 
 Java.lang.NoClassDefFoundError: a $ b 
 À a.main (a.Java:5) 
 Causée par: Java.lang.ClassNotFoundException: a $ b 
 À Java.net.URLClassLoader $ 1.run (URLClassLoader.Java:200) 
 À Java.security.AccessController.doPrivileged (Méthode native) 
 à Java.net.URLClassLoader.findClass (URLClassLoader.Java:188) 
 à Java.lang.ClassLoader.loadClass (ClassLoader.Java:307) à Sun.misc.Launcher $ AppClassLoader .loadClass (Launcher.Java:301) 
 à Java.lang.ClassLoader.loadClass (ClassLoader.Java:252) 
 à Java.lang.ClassLoader.loadClassInternal (ClassLoader.Java:320) 
 ... 1 de plus 
 
 Deuxième tentative nouvelle b (): 
 Java.lang.NoClassDefFoundError: a $ b 
 À aMain ( a.Java:7)

La première invocation aboutit à une exception ClassNotFoundException (émise par le chargeur de classes lorsqu'il ne peut pas trouver la classe), qui doit être encapsulée dans une NoClassDefFoundError non contrôlée, car le code en question (new b()) ne fonctionne que.

Bien entendu, la deuxième tentative échouera également, mais comme vous pouvez le constater, l'exception encapsulée n'en est plus une, car ClassLoader semble se souvenir des chargeurs de classe en échec. Vous ne voyez que le NCDFE sans aucune idée de ce qui s'est réellement passé.

Ainsi, si vous rencontrez un objet NCDFE sans cause fondamentale, vous devez voir si vous pouvez effectuer le suivi jusqu'au tout premier chargement de la classe pour rechercher la cause de l'erreur.

29
mogsie

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

ClassNotFoundException: survient lorsque le chargeur de classes n'a pas pu trouver la classe requise dans le chemin de classes. Donc, fondamentalement, vous devriez vérifier votre chemin de classe et ajouter la classe dans le chemin de classe.

NoClassDefFoundError: il est plus difficile de déboguer et de trouver la raison. Ceci est levé lorsque, au moment de la compilation, les classes requises sont présentes, mais qu'au moment de l'exécution, les classes sont modifiées ou supprimées ou que la classe initialise des exceptions statiques. Cela signifie que la classe en cours de chargement est présente dans classpath, mais l'une des classes requises par cette classe est soit supprimée, soit impossible à charger par le compilateur. Donc, vous devriez voir les classes qui dépendent de cette classe.

Exemple :

public class Test1
{
}


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

}

Maintenant, après la compilation des deux classes, si vous supprimez le fichier Test1.class et exécutez la classe Test, il lancera

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: levé lorsqu'une application tente de charger une classe par son nom, mais aucune définition de la classe portant le nom spécifié n'a pu être trouvée.

NoClassDefFoundError: levé si la machine virtuelle Java tente de charger la définition d'une classe et si aucune définition de la classe n'a pu être trouvée.

19
KingFeming

Quelle est la raison pour obtenir chacun d'eux et tout processus de réflexion sur la façon de traiter de telles erreurs?

Ils sont étroitement liés. Une ClassNotFoundException est levée lorsque Java cherche une classe particulière par son nom et ne peut pas la charger avec succès. Une NoClassDefFoundError est lancée lorsque Java cherche une classe liée à un code existant, mais ne la trouve pas pour une raison ou une autre (par exemple, un mauvais chemin de classe, une version incorrecte de Java , mauvaise version d’une bibliothèque) et est totalement fatale car elle indique que quelque chose s’est mal passé.

Si vous avez un arrière-plan C, un CNFE est comme un échec de dlopen()/dlsym() et un NCDFE est un problème avec l'éditeur de liens; dans le second cas, les fichiers de classe concernés n'auraient jamais dû être réellement compilés dans la configuration que vous essayez de les utiliser.

15
Donal Fellows

Exemple 1:

class A{
 void met(){
   Class.forName("com.example.Class1");
 }
}

Si com/example/Class1 n'existe dans aucun des chemins de classes, il jette ClassNotFoundException.

Exemple n ° 2:

Class B{
  void met(){
   com.example.Class2 c = new com.example.Class2();
 }
}

Si com/example/Class2 existait lors de la compilation de B, mais n’a pas été trouvé lors de l’exécution, il jette NoClassDefFoundError.

Les deux sont des exceptions d'exécution.

11
Dinesh

ClassNotFoundException est levé lorsqu'il y a une tentative de chargement de la classe en la référençant via une chaîne. Par exemple, le paramètre dans Class.forName () est une chaîne, ce qui augmente le risque que des noms binaires non valides soient transmis au chargeur de classes.

L'exception ClassNotFoundException est levée lorsqu'un nom binaire potentiellement non valide est rencontré. Par exemple, si le nom de la classe a le caractère '/', vous êtes lié à une exception ClassNotFoundException. Il est également lancé lorsque la classe directement référencée n'est pas disponible sur le classpath.

D'autre part, NoClassDefFoundError est levé

  • lorsque la représentation physique réelle de la classe - le fichier .class est indisponible,
  • ou la classe a déjà été chargée dans un chargeur de classe différent (généralement, un chargeur de classe parent aurait chargé la classe et par conséquent, la classe ne peut pas être chargée à nouveau),
  • ou si une définition de classe incompatible a été trouvée - le nom dans le fichier de classe ne correspond pas au nom demandé,
  • ou (surtout) si une classe dépendante ne peut pas être localisée et chargée. Dans ce cas, la classe directement référencée peut avoir été localisée et chargée, mais la classe dépendante n'est pas disponible ou ne peut pas être chargée. Il s'agit d'un scénario dans lequel la classe directement référencée peut être chargée via un Class.forName ou des méthodes équivalentes. Cela indique une défaillance de la liaison.

En bref, une erreur NoClassDefFoundError est généralement générée sur les instructions new () ou les invocations de méthode qui chargent une classe précédemment absente (par opposition au chargement de classes basé sur une chaîne pour ClassNotFoundException), lorsque le chargeur de classes est incapable de trouver ou de charger la définition de classe ( s).

Finalement, il appartient à l'implémentation de ClassLoader d'envoyer une instance de ClassNotFoundException lorsqu'il est impossible de charger une classe. La plupart des implémentations de chargeur de classe personnalisées effectuent cette opération car elles étendent URLClassLoader. Habituellement, les chargeurs de classes ne lancent pas explicitement une erreur NoClassDefFoundError sur les implémentations de méthodes. Cette exception est généralement émise depuis la machine virtuelle Java du compilateur HotSpot, et non par le chargeur de classes lui-même.

9
Vineet Reynolds

Différence entre ClassNotFoundException Vs NoClassDefFoundError

enter image description here

8
Lawakush Kurmi

Avec les noms eux-mêmes, nous pouvons facilement identifier un élément parmi Exception et un autre élément parmi Error.

Exception: Des exceptions se produisent pendant l'exécution du programme. Un programmeur peut gérer ces exceptions en essayant catch block. Nous avons deux types d'exceptions. Exception contrôlée qui lève à la compilation. Exceptions d'exécution levées au moment de l'exécution, ces exceptions se produisent généralement à cause d'une mauvaise programmation.

Erreur: Ce ne sont pas du tout des exceptions, cela dépasse la portée du programmeur. Ces erreurs sont généralement générées par la machine virtuelle Java.


enter image description heresource de l'image

Différence:

ClassNotFoundException:

  • Le chargeur de classes ne parvient pas à vérifier un code d'octet de classe mentionné dans Phase de liaison du sous-système de chargement de classe , nous obtenons ClassNotFoundException.
  • ClassNotFoundException est une exception vérifiée dérivée directement de la classe Java.lang.Exception et vous devez la gérer de manière explicite.
  • ClassNotFoundException apparaît lorsqu'il y a un chargement explicite de la classe impliqué en fournissant le nom de la classe au moment de l'exécution à l'aide de ClassLoader.loadClass (), Class .forName () et ClassLoader.findSystemClass ().

NoClassDefFoundError:

  • Le chargeur de classes ne parvient pas à résoudre les références d'une classe en Phase de liaison de Sous-système de chargement de classe nous obtenons NoClassDefFoundError.
  • NoClassDefFoundError est une erreur dérivée de LinkageError class, utilisée pour indiquer les cas d'erreur, où une classe a une dépendance sur une autre classe et que cette classe a changé après la compilation.
  • NoClassDefFoundError est le résultat d'un chargement implicite de la classe en raison d'un appel de méthode de cette classe ou de tout accès à une variable.

Similitudes:

  • NoClassDefFoundError et ClassNotFoundException sont tous deux liés à l'indisponibilité d'une classe au moment de l'exécution.
  • ClassNotFoundException et NoClassDefFoundError sont tous deux liés à Java chemin de classe.
8
Premraj

Étant donné les actions sussystem du chargeur de classe:

http://www.artima.com/insidejvm/ed2/images/fig7-1.gif

Ceci est un article qui m'a beaucoup aidé à comprendre la différence: http://docs.Oracle.com/javase/specs/jvms/se7/html/jvms-5.html

Si une erreur se produit lors du chargement de la classe, une instance d'une sous-classe de LinkageError doit être renvoyée à un point du programme qui utilise (directement ou indirectement) la classe ou l'interface en cours de chargement.

Si la machine virtuelle Java tente de charger une classe C pendant la vérification (§ 5.4.1) ou la résolution (§ 5.4.3) (mais pas l'initialisation (§ 5.5)), et le chargeur de classes qui est utilisé pour lancer le chargement de C lève une instance de ClassNotFoundException , puis la machine virtuelle Java doit lancer une instance de NoClassDefFoundError dont la cause est l'instance de ClassNotFoundException .

Donc, un ClassNotFoundException est une cause première de NoClassDefFoundError .
Et un NoClassDefFoundError est un cas particulier d'erreur de chargement de type, qui se produit à Lien étape.

3
Anton Shchastnyi

Ajoutez une raison possible dans la pratique:

  • ClassNotFoundException: comme le dit Cletus, vous utilisez une interface alors que la classe d’interface héritée n’est pas dans le chemin de classe. E.g, modèle de fournisseur de service (ou service locator ) essaie de localiser une classe non existante
  • NoClassDefFoundError: la classe donnée est trouvée alors que la dépendance de la classe donnée est introuvable

En pratique, Une erreur peut être levée silencieusement , par exemple, vous soumettez une tâche de minuteur et dans la tâche de minuteur, elle lève Erreur , alors que dans la plupart des cas, votre programme n’attrape que Exception . La boucle principale est terminée sans aucune information. Une erreur similaire à NoClassDefFoundError est ExceptionInInitializerError , lorsque votre initialiseur statique ou l'initialiseur d'une variable statique lève une exception.

2
leef

ClassNotFoundException est une exception vérifiée qui se produit lorsque nous demandons à JVM de charger une classe par son nom de chaîne à l'aide de Class.forName () ou ClassLoader.findSystemClass () ou Les méthodes ClassLoader.loadClass () et la classe mentionnée sont introuvables 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 comporte pas de fichier JAR.

NoClassDefFoundError une erreur se produit lorsque JVM essaie de charger une classe particulière faisant partie de l'exécution du code (dans le cadre d'un appel de méthode normal ou dans le cadre de la création une instance utilisant le nouveau mot-clé) et cette classe n’est pas présente dans votre chemin de classe mais était présente au moment de la compilation car pour exécuter votre programme, vous devez le compiler et si vous essayez d’utiliser une classe qui n’est pas présente, le compilateur lève la compilation Erreur.

Ci-dessous la brève description

enter image description here

Vous pouvez lire Tout ce qui concerne ClassNotFoundException vs NoClassDefFoundError pour plus de détails.

1
Naresh Joshi

Je me rappelle ce qui suit encore et encore lorsque j'ai besoin de rafraîchir

ClassNotFoundException

Hiérarchie de classe

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

Pendant le débogage

  1. Jar requis, la classe est absente du classpath.
  2. Vérifiez que tous les fichiers JAR requis sont dans le classpath de jvm.

NoClassDefFoundError

Hiérarchie de classe

NoClassDefFoundError extends LinkageError  extends Error extends Throwable

Pendant le débogage

  1. Problème de chargement dynamique d'une classe compilée correctement
  2. Problème avec les blocs statiques, les constructeurs, les méthodes init () de la classe dépendante et l'erreur réelle est encapsulée par plusieurs couches [surtout lorsque vous utilisez spring, hibernate l'exception réelle est encapsulée et vous obtiendrez NoClassDefError]
  3. Lorsque vous faites face à "ClassNotFoundException" sous un bloc statique de classe dépendante
  4. Problème avec les versions de la classe. Cela se produit lorsque vous avez deux versions v1, v2 de la même classe sous différents jar/packages, qui ont été compilées avec succès à l'aide de v1 et que la v2 est chargée au moment de l'exécution sans les méthodes/vars appropriées et vous verrez cette exception. [J'ai une fois résolu ce problème en supprimant la copie de la classe liée à log4j sous plusieurs fichiers jar apparaissant dans le chemin de classe]
0
147.3k

ClassNotFoundException et NoClassDefFoundError se produisent lorsqu'une classe particulière n'est pas trouvée au moment de 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'une 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