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

StackOverflow https://stackoverflow.com/questions/1457863

Question

Quelle est la différence entre NoClassDefFoundError et ClassNotFoundException?

Ce qui les amène à être jeté? Comment peuvent-ils être résolus?

Je rencontre souvent ces Throwables lors de la modification du code existant pour inclure de nouveaux fichiers jar. Je les ai frappé à la fois du côté client et côté serveur pour une application java distribuée par webstart.

Les raisons possibles, je suis venu à travers:

  1. paquets non inclus dans build.xml pour le côté client de code
  2. exécution classpath manquantes pour les nouveaux pots que nous utilisons
  3. les conflits de version avec pot précédent

Quand je rencontre ces aujourd'hui je prends une approche piste et erreurs pour faire fonctionner les choses. Je besoin de plus de clarté et de compréhension.

Était-ce utile?

La solution

La différence de l'API Java Spécifications se présente comme suit.

ClassNotFoundException :

  

levée lorsqu'une application tente de   charge dans une classe à travers sa chaîne   nom en utilisant:

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

mais pas de définition pour la classe   le nom spécifié est introuvable.

NoClassDefFoundError :

  

Jeté si la machine virtuelle Java ou   une instance ClassLoader tente de charger   dans la définition d'une classe (dans le cadre   d'un appel de méthode normale ou en tant que partie de   la création d'une nouvelle instance en utilisant la nouvelle   expression) et aucune définition du   n'a pu être trouvée classe.

     

La définition de classe pour effectuer des recherches   existait lorsque l'en cours d'exécution   classe a été compilée, mais la définition   ne peut plus être trouvé.

Alors, il semble que le NoClassDefFoundError se produit lorsque la source a été compilé avec succès, mais lors de l'exécution, les fichiers class requis n'a pas été trouvé. Cela peut être quelque chose qui peut se produire dans la distribution ou la production de fichiers JAR, lorsque tous les fichiers class nécessaires ont été inclus.

En ce qui concerne ClassNotFoundException, il semble qu'il peut provenir d'essayer de faire des appels de réflexion à des classes à l'exécution, mais les classes du programme tente d'appeler est n'existe pas.

La différence entre les deux est que l'on est un Error et l'autre est un Exception. Avec NoClassDefFoundError est un Error et il provient de la machine virtuelle Java ayant des difficultés à trouver une classe, il devrait trouver. Un programme qui devait travailler à la compilation ne peut pas exécuter en raison de class fichiers non trouvé, ou n'est pas le même que celui produit ou rencontré lors de la compilation. Ceci est une erreur assez critique, car le programme ne peut être lancé par la machine virtuelle Java.

D'autre part, la ClassNotFoundException est un Exception, donc il est un peu attendu, et est quelque chose qui est récupérable. En utilisant la réflexion est peut être sujette aux erreurs (car il y a des attentes que les choses ne peuvent pas aller comme prévu. Il n'y a pas de vérification de compilation pour voir que toutes les classes requises existent, donc aucun problème à trouver les classes désirées apparaîtront à l'exécution .

Autres conseils

A ClassNotFoundException est levée lorsque la classe déclarée ne se trouve pas par le ClassLoader. Cela signifie généralement que la classe est absente de la CLASSPATH. Cela pourrait également signifier que la classe en question tente de charger d'une autre classe qui a été chargé dans une classloader mère et donc la classe de l'enfant classloader n'est pas visible. Cela est parfois le cas lorsque l'on travaille dans des environnements plus complexes comme un serveur App (WebSphere est tristement célèbre pour ces problèmes de classloader).

Les gens ont souvent tendance à confondre java.lang.NoClassDefFoundError avec java.lang.ClassNotFoundException mais il y a une distinction importante. Par exemple, une exception (une erreur vraiment depuis 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 est pas dans le CLASSPATH. Enfait son tout à fait le contraire. Cela signifie que la ActiveMQConnectionFactory de classe a été trouvée par le ClassLoader mais en essayant de charger la classe, il a couru dans une erreur de 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'est pas trouvé par le ClassLoader. Donc, pour trouver le coupable, voir la source de la classe en question (ActiveMQConnectionFactory dans ce cas) et rechercher le code en utilisant des blocs statiques ou des membres statiques. Si vous n'avez pas accès à la source, puis simplement décompiler à l'aide JAD.

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

private static SomeClass foo = new SomeClass();

Astuce: Pour savoir quel pot une classe appartient, vous pouvez utiliser le site Web jarFinder. Cela vous permet de spécifier un nom de classe à l'aide des caractères génériques et il recherche la classe dans sa base de données de pots. jarhoo vous permet de faire la même chose, mais ce ne est plus libre d'utiliser.

Si vous souhaitez localiser le pot qui une classe appartient à un chemin d'accès local, vous pouvez utiliser un utilitaire comme jarscan ( http://www.inetfeedback.com/jarscan/ ). Vous devez spécifier la classe que vous souhaitez localiser et le chemin du répertoire racine où vous souhaitez qu'il commencer à chercher de la classe dans des bocaux et des fichiers zip.

NoClassDefFoundError est une erreur de liaison essentiellement. Il se produit lorsque vous essayez d'instancier un objet (statiquement avec « nouveau ») et il est pas trouvé quand il était lors de la compilation.

ClassNotFoundException est plus générale et 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 accepte une interface et que quelqu'un passe dans une classe qui implémente cette interface, mais vous ne disposez pas d'un accès à la classe. Elle couvre également le cas de chargement de classe dynamique, comme l'utilisation loadClass() ou Class.forName().

A NoClassDefFoundError (NCDFE) se produit lorsque votre code est exécuté "nouveau Y ()" et il ne peut pas trouver la classe Y.

Il peut être simplement que Y est absent de votre chargeur de classe comme les autres commentaires suggèrent, mais il se pourrait que la classe Y est pas signé ou a une signature non valide, ou que Y est chargé par un autre classloader non visible à votre code, ou même que Y dépend de Z qui ne pouvait être chargé pour l'une des raisons ci-dessus.

Si cela se produit, la machine virtuelle Java se rappelleront le résultat de X de chargement (NCDFE) et il sera tout simplement jeter un nouveau NCDFE chaque fois que vous demandez Y sans vous dire pourquoi:

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

enregistrer comme a.java quelque part

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

Compiler le code avec javac a.java Ensuite, exécutez une en invoquant java -cp . a -. Il devrait simplement imprimer deux lignes de texte, et il devrait fonctionner sans erreurs

Ensuite, supprimez le fichier « un b.class de $ » (ou le remplir avec les ordures, ou copier a.class dessus) pour simuler la classe manquant ou endommagé. Voici ce qui se passe:

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)

Les premiers résultats d'invocation dans une ClassNotFoundException (lancée par le chargeur de classe quand il ne trouve pas la classe), qui doit être enveloppé dans une décochée NoClassDefFoundError, puisque le code en question (new b()) devrait fonctionner.

La seconde tentative bien sûr échouer aussi, mais comme vous pouvez voir l'exception enveloppé est plus, parce que le ClassLoader semble se souvenir de chargeurs de classe ont échoué. Vous ne voyez que le NCDFE absolument aucune idée de ce qui est arrivé.

Donc, si jamais vous voyez un NCDFE sans cause racine, vous devez voir si vous pouvez remonter jusqu'à la première fois la classe a été chargé de trouver la cause de l'erreur.

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

ClassNotFoundException : se produit lorsque chargeur de classe n'a pas pu trouver la classe requise dans le chemin de la classe. Donc, en gros, vous devriez vérifier votre chemin de classe et ajouter la classe dans le classpath.

NoClassDefFoundError : il est plus difficile à déboguer et trouver la raison. Ceci est jeté quand au moment de la compilation des classes requises sont présentes, mais au moment de l'exécution des classes sont modifiées ou supprimées ou statiques de la classe initialise a jeté des exceptions. Cela signifie que la classe qui se charge est présent dans classpath, mais l'une des classes qui sont requises par cette classe sont soit supprimés ou n'a pas pu 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();    
   }

}

après la compilation de deux classes, si vous supprimez le fichier Test1.class et exécutez la classe de test, il jeter

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:. Jeté lorsqu'une application tente de charger dans une classe par son nom, mais pas de définition de la classe se trouve le nom spécifié

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

  

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

Ils sont étroitement liés. Une ClassNotFoundException est levée lorsque Java est allé chercher une classe particulière par son nom et n'a pas pu charger avec succès. Une NoClassDefFoundError est levée lorsque Java est allé chercher une classe qui a été liée à un code existant, mais il n'a pas pu trouver pour une raison ou une autre (par exemple, mauvaise classpath, mauvaise version de Java, mauvaise version d'une bibliothèque) et est tout à fait fatale car elle indique que quelque chose a mal tourné.

Si vous avez un fond de C, un CNFE est comme un échec à dlopen() / dlsym() et un NCDFE est un problème avec l'éditeur de liens; dans le second cas, les fichiers de classe concernés ne devraient jamais ont été effectivement compilé dans la configuration que vous essayez de les utiliser.

Exemple 1:

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

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

Exemple # 2:

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

Si com/example/Class2 existait lors de la compilation B, mais pas trouvé en exécution, il jette NoClassDefFoundError.

Les deux exceptions sont gérées de temps.

ClassNotFoundException est jeté quand il y a tenter de charger la classe en faisant référence via une chaîne. Par exemple, le paramètre dans Class.forName () est une chaîne, et cela augmente le potentiel des noms binaires non valides transmis au classloader.

Le ClassNotFoundException est jeté quand un nom binaire potentiellement invalide est rencontrée; par exemple, si le nom de classe a le caractère « / », vous êtes tenu d'obtenir un ClassNotFoundException. Il est également levée lorsque la classe référencée directement est pas disponible sur le chemin de classe.

Par contre, NoClassDefFoundError est jeté

  • lorsque la représentation physique de la classe - le fichier .class est indisponible,
  • ou la classe déjà été chargés dans un autre classloader (généralement un parent classloader aurait chargé la classe et donc la classe ne peut pas être à nouveau chargé),
  • ou si une définition de classe incompatible a été trouvé - le nom dans le fichier de classe ne correspond pas au nom demandé,
  • ou (le plus important) sinon peut être localisé et chargé d'une classe dépendante. Dans ce cas, la classe référencée directement aurait été localisé et chargé, mais la classe dépendante ne sont pas disponibles ou ne peut pas être chargé. Ceci est un scénario dans lequel la classe référencée directement peut être chargée via un Class.forName ou des méthodes équivalentes. Cela indique une défaillance dans la liaison.

En bref, un NoClassDefFoundError est généralement jeté sur les nouvelles () déclarations ou invocations de méthode qui charge une classe précédemment absent (par opposition à la charge basée sur une chaîne de classes pour ClassNotFoundException), lorsque le classloader ne parvient pas à trouver ou charger le définition de classe (s).

Finalement, il est jusqu'à la mise en œuvre de ClassLoader de lancer une instance de ClassNotFoundException quand il est impossible de charger une classe. La plupart des implémentations de classloader personnalisés effectuent cela car ils étendent la URLClassLoader. Habituellement classloaders ne pas jeter explicitement NoClassDefFoundError sur l'une des implémentations de méthode -. Cette exception est généralement jeté de la machine virtuelle Java dans le compilateur HotSpot, et non par le classloader lui-même

Différence entre ClassNotFoundException Vs NoClassDefFoundError

 ici

  

nous pouvons facilement avec les noms s'identifions un de Exception et l'autre est de Error.

Exception: exception se produit pendant l'exécution du programme. Un programmeur peut gérer ces exceptions par essayer bloc catch. Nous avons deux types d'exceptions. exception contrôlée qui jette au moment de la compilation. Exceptions d'exécution qui sont lancées au moment de l'exécution, ces exceptions se produisent généralement à cause de la mauvaise programmation.

Erreur: Ce ne sont pas des exceptions à tout, il est hors de la portée du programmeur. Ces erreurs sont généralement lancées par JVM.


image source

différence:

ClassNotFoundException:

  • chargeur de classe ne parvient pas à vérifier un code d'octet de classe que nous mentionnons dans Phase Link du sous-système de chargement class nous obtenons ClassNotFoundException.
  • ClassNotFoundException est une exception contrôlée directement dérivée de la classe de java.lang.Exception et vous devez fournir une gestion explicite pour elle
  • ClassNotFoundException arrive quand il y a une classe de est impliqué chargement explicite en fournissant le nom de la classe lors de l'exécution en utilisant ClassLoader.loadClass (), Class.forName () et ClassLoader.findSystemClass ().

NoClassDefFoundError:

  • chargeur de classe ne parvient pas à résolution références d'une classe Phase Link du sous-système de chargement classe nous obtenons NoClassDefFoundError.
  • NoClassDefFoundError est une erreur dérivée de la classe de LinkageError, qui est utilisé pour indiquer les cas d'erreur, où une classe a une dépendance à une autre classe et que la classe a changé après la façon incompatible compilation.
  • NoClassDefFoundError est un résultat de chargement implicite de classe en raison d'un appel de méthode de cette classe ou de tout accès variable.

Similitudes:

  • Les deux NoClassDefFoundError et ClassNotFoundException sont liés à l'indisponibilité d'une classe à l'exécution.
  • Les deux ClassNotFoundException et NoClassDefFoundError sont liés à Java classpath.

Compte tenu des actions de la classe chargeur:

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 pendant le chargement de la classe, puis une instance d'un   sous-classe de LinkageError doit être jeté à un point dans le programme   (Directement ou indirectement) utilise la classe ou l'interface en cours de chargement.

     

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

ClassNotFoundException est une cause racine de NoClassDefFoundError .
Et NoClassDefFoundError est un cas particulier d'erreur de chargement de type, qui se produit à Lier étape.

ClassNotFoundException est une exception contrôlée qui se produit lorsque nous disons machine virtuelle Java pour charger une classe par son nom de chaîne en utilisant des méthodes Class.forName () ou ClassLoader.findSystemClass () ou ClassLoader.loadClass () et mentionné classe ne se trouve pas dans le chemin de classe.

La plupart du temps, cette exception se produit lorsque vous essayez d'exécuter une application sans mise à jour du classpath avec les fichiers JAR requis. Par exemple, vous avez peut-être vu cette exception lorsque vous faites le code JDBC pour se connecter à la base de données i.e.MySQL mais votre classpath ne dispose pas JAR pour elle.

NoClassDefFoundError erreur se produit lorsque JVM tente de charger une classe particulière qui est la partie de votre exécution de code (dans le cadre d'un appel de méthode normal ou dans le cadre de la création d'une instance en utilisant le nouveau mot-clé) et cette classe n'est pas présent dans votre classpath, mais était présent au moment de la compilation parce que, pour l'exécution de votre programme, vous devez compiler et si vous essayez d'utiliser une classe qui n'est pas présent compilateur soulèvera erreur de compilation.

Ci-dessous la brève description

Vous pouvez lire Tout sur ClassNotFoundException Vs NoClassDefFoundError pour plus de détails.

Je me rappelle ce qui suit encore et encore quand je dois rafraîchir

ClassNotFoundException

Hiérarchie des classes

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

Lors du débogage

  1. jar requis, la classe est absente de la classpath.
  2. Vérifier tous les pots nécessaires sont en classpath de jvm.

NoClassDefFoundError

Hiérarchie des classes

NoClassDefFoundError extends LinkageError  extends Error extends Throwable

Lors du débogage

  1. Problème avec le chargement d'une classe dynamique, qui a été compilé correctement
  2. Problème avec des blocs statiques, les constructeurs, les méthodes init () de la classe dépendante et l'erreur réelle est enveloppée par plusieurs couches [en particulier lorsque vous utilisez printemps, mise en veille prolongée l'exception réelle est enveloppé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 classe. Cela se produit lorsque vous avez deux versions v1, v2 de même classe sous différents pot / packages, qui a été compilé avec succès v1 et v2 est chargé à l'exécution qui ne possède pas des méthodes pertinentes / vars et vous verrez cette exception. [Une fois, je résolu ce problème en supprimant le double de log4j classe associée dans plusieurs pots qui est apparu dans le classpath]

ClassNotFoundException et NoClassDefFoundError se produisent quand une classe particulière ne se trouve pas à runtime.However, ils se produisent à différents scénarios.

ClassNotFoundException est une exception qui se produit lorsque vous essayez de charger une classe à l'exécution en utilisant des méthodes et des classes mentionnées Class.forName () ou loadClass () ne se trouvent pas dans le chemin de classe.

    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 quand une classe particulière est présente au moment de la compilation, mais il 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 système 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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top