Welche Ursachen und was sind die Unterschiede zwischen NoClassDefFoundError und ClassNotFoundException?

371

Was ist der Unterschied zwischen NoClassDefFoundErrorund ClassNotFoundException?

Was bewirkt, dass sie geworfen werden? Wie können sie gelöst werden?

Ich stoße häufig auf diese Throwables, wenn ich vorhandenen Code so ändere, dass er neue JAR-Dateien enthält. Ich habe sie sowohl auf der Client- als auch auf der Serverseite für eine über Webstart verteilte Java-App getroffen.

Mögliche Gründe, auf die ich gestoßen bin:

  1. Pakete, die build.xmlfür die Client-Seite des Codes nicht enthalten sind
  2. Der Laufzeitklassenpfad fehlt für die neuen Jars, die wir verwenden
  3. Version widerspricht dem vorherigen Glas

Wenn ich heute auf diese stoße, verfolge ich einen Trail-and-Error-Ansatz, um die Dinge zum Laufen zu bringen. Ich brauche mehr Klarheit und Verständnis.

krisp
quelle
Ich finde es oft hilfreich , die JVM mit -verbose(z. B. -verbose:class -verbose:jni) zu betreiben - aber Mogsie berichtet unter ihrer Antwort, dass dies keine zusätzlichen nützlichen Informationen liefert :(
PJTraill

Antworten:

388

Der Unterschied zu den Java-API-Spezifikationen ist wie folgt.

Für ClassNotFoundException:

Wird ausgelöst, wenn eine Anwendung versucht, eine Klasse über ihren Zeichenfolgennamen zu laden, indem sie Folgendes verwendet:

  • Die forNameMethode in der Klasse Class.
  • Die findSystemClassMethode in der Klasse ClassLoader.
  • Die loadClassMethode in der Klasse ClassLoader.

Es konnte jedoch keine Definition für die Klasse mit dem angegebenen Namen gefunden werden.

Für NoClassDefFoundError:

Wird ausgelöst, wenn die Java Virtual Machine oder eine ClassLoaderInstanz versucht, die Definition einer Klasse zu laden (als Teil eines normalen Methodenaufrufs oder als Teil der Erstellung einer neuen Instanz mit dem neuen Ausdruck) und keine Definition der Klasse gefunden werden konnte.

Die gesuchte Klassendefinition war vorhanden, als die aktuell ausgeführte Klasse kompiliert wurde, aber die Definition kann nicht mehr gefunden werden.

Es scheint also, dass dies NoClassDefFoundErrorauftritt, wenn die Quelle erfolgreich kompiliert wurde, aber zur Laufzeit die erforderlichen classDateien nicht gefunden wurden. Dies kann bei der Verteilung oder Produktion von JAR-Dateien vorkommen, bei denen nicht alle erforderlichen classDateien enthalten waren.

Was ClassNotFoundExceptionscheint es , dass es von dem Versuch stammen können reflektierende Anrufe Klassen zur Laufzeit zu machen, aber die Klassen das Programm zum Aufruf versucht wird , existiert nicht.

Der Unterschied zwischen den beiden ist, dass einer ein Errorund der andere ein ist Exception. Mit NoClassDefFoundErrorist ein Errorund es entsteht, wenn die Java Virtual Machine Probleme hat, eine Klasse zu finden, die sie voraussichtlich finden wird. Ein Programm, von dem erwartet wurde, dass es zur Kompilierungszeit funktioniert, kann nicht ausgeführt werden, da classDateien nicht gefunden wurden oder nicht mit den zur Kompilierungszeit erstellten oder angetroffenen Dateien identisch sind. Dies ist ein ziemlich kritischer Fehler, da das Programm nicht von der JVM initiiert werden kann.

Auf der anderen Seite ist das ClassNotFoundExceptionein Exception, also wird es etwas erwartet und ist etwas, das wiederhergestellt werden kann. Die Verwendung von Reflection kann fehleranfällig sein (da einige Erwartungen bestehen, dass die Dinge möglicherweise nicht wie erwartet verlaufen. Es wird nicht überprüft, ob alle erforderlichen Klassen vorhanden sind, sodass zur Laufzeit alle Probleme beim Auffinden der gewünschten Klassen auftreten .

Coobird
quelle
53
NoClassDefFoundErrortritt normalerweise auf, wenn ein Problem (Ausnahme ausgelöst) mit der Initialisierung des statischen Blocks oder der statischen Felder der Klasse vorliegt, sodass die Klasse nicht erfolgreich initialisiert werden kann.
Dagang
7
upvote. einer ist ein Errorund der andere ist ein Exception. :)
Ravi
83

Eine ClassNotFoundException wird ausgelöst, wenn die gemeldete Klasse vom ClassLoader nicht gefunden wird. Dies bedeutet normalerweise, dass die Klasse im CLASSPATH fehlt. Dies kann auch bedeuten, dass die betreffende Klasse versucht, aus einer anderen Klasse geladen zu werden, die in einen übergeordneten Klassenladeprogramm geladen wurde, und daher die Klasse aus dem untergeordneten Klassenladeprogramm nicht sichtbar ist. Dies ist manchmal der Fall, wenn Sie in komplexeren Umgebungen wie einem App Server arbeiten (WebSphere ist für solche Classloader-Probleme berüchtigt).

Menschen neigen dazu , häufig zu verwechseln java.lang.NoClassDefFoundErrormit java.lang.ClassNotFoundExceptionaber es gibt einen wichtigen Unterschied. Zum Beispiel eine Ausnahme (ein Fehler, der wirklich da java.lang.NoClassDefFoundErroreine Unterklasse von java.lang.Error ist) wie

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

bedeutet nicht, dass sich die ActiveMQConnectionFactory-Klasse nicht im CLASSPATH befindet. Tatsächlich ist es genau das Gegenteil. Dies bedeutet, dass die Klasse ActiveMQConnectionFactory vom ClassLoader gefunden wurde. Beim Versuch, die Klasse zu laden, trat jedoch ein Fehler beim Lesen der Klassendefinition auf. Dies geschieht normalerweise, wenn die betreffende Klasse statische Blöcke oder Mitglieder hat, die eine Klasse verwenden, die vom ClassLoader nicht gefunden wird. Um den Täter zu finden, zeigen Sie die Quelle der betreffenden Klasse an (in diesem Fall ActiveMQConnectionFactory) und suchen Sie mithilfe statischer Blöcke oder statischer Elemente nach Code. Wenn Sie keinen Zugriff auf die Quelle haben, dekompilieren Sie sie einfach mit JAD.

Wenn Sie den Code untersuchen, sagen Sie, dass Sie eine Codezeile wie unten finden, stellen Sie sicher, dass die Klasse SomeClass in Ihrem CLASSPATH enthalten ist.

private static SomeClass foo = new SomeClass();

Tipp: Um herauszufinden, zu welchem ​​Jar eine Klasse gehört, können Sie die Website jarFinder verwenden. Auf diese Weise können Sie einen Klassennamen mithilfe von Platzhaltern angeben und in der JAR-Datenbank nach der Klasse suchen. Mit jarhoo können Sie dasselbe tun, es ist jedoch nicht mehr kostenlos zu verwenden.

Wenn Sie in einem lokalen Pfad herausfinden möchten, zu welchem ​​JAR eine Klasse gehört, können Sie ein Dienstprogramm wie jarscan ( http://www.inetfeedback.com/jarscan/ ) verwenden. Geben Sie einfach die Klasse an, die Sie suchen möchten, und den Stammverzeichnispfad, in dem die Suche nach der Klasse in Jars und Zip-Dateien beginnen soll.

Sanjiv Jivan
quelle
9
Es ist lustig, dass dies genau die richtige Antwort ist, die als letzte gewählt wurde. (Sogar -1 bevor ich abgestimmt habe). ClassNotFoundException bedeutet, dass der CL keine .class-Datei sieht. NoClassDefFoundError bedeutet, dass die .class-Datei vorhanden ist und nicht geladen werden kann (möglicherweise JNI-Fehler).
user43685
1
Widerspricht diese Antwort nicht dem Antwortformular coobird?
Zardosht
Ich habe ein ähnliches Beispiel für einen statischen Block ausprobiert. Meine Klasse Class1 hat die statische Variable "private static B foo = new B ();" Nach dem Kompilieren habe ich die B.class-Datei aus dem bin-Ordner entfernt. Nun von der Hauptmethode der dritten Klasse, wenn ich ein Objekt der Klasse 1 erstelle. Der Fehler wird wie folgt angezeigt: -------- "Ausnahme im Thread" main "java.lang.NoClassDefFoundError: spring / B" ........ Es wird also genau angegeben, welche Klasse nicht gefunden wurde Die Klasse bezieht sich auf den statischen Block und nicht auf die äußere Klasse. Dies widerspricht dieser Antwort.
Kaushik Lele
+1 für die Klarstellung bezüglich "bedeutet nicht, dass die ActiveMQConnectionFactory-Klasse nicht im CLASSPATH ist"
akila
35

NoClassDefFoundErrorist im Grunde ein Verknüpfungsfehler. Es tritt auf, wenn Sie versuchen, ein Objekt zu instanziieren (statisch mit "neu"), und es wird nicht gefunden, als es während der Kompilierung war.

ClassNotFoundExceptionist allgemeiner und stellt eine Laufzeitausnahme dar, wenn Sie versuchen, eine nicht vorhandene Klasse zu verwenden. Sie haben beispielsweise einen Parameter in einer Funktion, der eine Schnittstelle akzeptiert, und jemand übergibt eine Klasse, die diese Schnittstelle implementiert, aber Sie haben keinen Zugriff auf die Klasse. Es wird auch der Fall des Ladens dynamischer Klassen behandelt, z. B. die Verwendung von loadClass()oder Class.forName().

Cletus
quelle
29

Ein NoClassDefFoundError (NCDFE) tritt auf, wenn Ihr Code "new Y ()" ausführt und die Y-Klasse nicht gefunden werden kann.

Es kann einfach sein, dass Y in Ihrem Klassenladeprogramm fehlt, wie die anderen Kommentare vermuten lassen, aber es kann sein, dass die Y-Klasse nicht signiert ist oder eine ungültige Signatur hat oder dass Y von einem anderen Klassenladeprogramm geladen wird, das für Ihren Code nicht sichtbar ist oder sogar, dass Y von Z abhängt, das aus einem der oben genannten Gründe nicht geladen werden konnte.

In diesem Fall merkt sich die JVM das Ergebnis des Ladens von X (NCDFE) und wirft jedes Mal, wenn Sie nach Y fragen, einfach ein neues NCDFE, ohne Ihnen mitzuteilen, warum:

Klasse a {
  statische Klasse b {}
  public static void main (String args []) {
    System.out.println ("Erster Versuch neu b ():");
    try {new b (); } catch (Throwable t) {t.printStackTrace ();}
    System.out.println ("\ nZweiger Versuch new b ():");
    try {new b (); } catch (Throwable t) {t.printStackTrace ();}
  }}
}}

Speichern Sie dies irgendwo als a.java

Der Code versucht einfach zweimal, eine neue "b" -Klasse zu instanziieren, ansonsten hat er keine Fehler und tut nichts.

Kompilieren Sie den Code mit javac a.java. Führen Sie dann a durch Aufrufen aus. java -cp . aEs sollte nur zwei Textzeilen ausdrucken und fehlerfrei funktionieren.

Löschen Sie dann die Datei "a $ b.class" (oder füllen Sie sie mit Müll oder kopieren Sie eine Klasse darüber), um die fehlende oder beschädigte Klasse zu simulieren. Folgendes passiert:

Erster Versuch neu b ():
java.lang.NoClassDefFoundError: a $ b
    um a.main (a.java:5)
Auslöser: java.lang.ClassNotFoundException: a $ b
    bei java.net.URLClassLoader $ 1.run (URLClassLoader.java:200)
    at java.security.AccessController.doPrivileged (native Methode)
    bei java.net.URLClassLoader.findClass (URLClassLoader.java:188)
    bei java.lang.ClassLoader.loadClass (ClassLoader.java:307)
    at sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:301)
    bei java.lang.ClassLoader.loadClass (ClassLoader.java:252)
    bei java.lang.ClassLoader.loadClassInternal (ClassLoader.java:320)
    ... 1 mehr

Zweiter Versuch neu b ():
java.lang.NoClassDefFoundError: a $ b
    um a.main (a.java:7)

Der erste Aufruf führt zu einer ClassNotFoundException (durch den Klassenlader geworfen , wenn es nicht die Klasse finden kann), die in einem ungeprüften NoClassDefFoundError gewickelt werden müssen, da der Code in Frage ( new b()) soll nur Arbeit.

Der zweite Versuch schlägt natürlich ebenfalls fehl, aber wie Sie sehen, ist die umschlossene Ausnahme nicht mehr vorhanden, da sich der ClassLoader an fehlgeschlagene Klassenlader zu erinnern scheint. Sie sehen nur die NCDFE, die absolut keine Ahnung hat, was wirklich passiert ist.

Wenn Sie also jemals ein NCDFE ohne Grundursache sehen, müssen Sie prüfen, ob Sie bis zum ersten Laden der Klasse zurückverfolgen können, um die Fehlerursache zu finden.

Mogsie
quelle
Was ist mit der Ausführung der JVM mit -verboseoder einer ähnlichen Option, abhängig von der jeweiligen JVM? Wahrscheinlich -verbose:class, vielleicht -verbose:class:jnibei Verwendung von JNI, aber ich bin mir über die Syntax nicht sicher. Wenn dies nützlich ist, können Sie möglicherweise die Ergebnisse anzeigen.
PJTraill
Weder -verbose:classnoch -verbose:jnizusätzliche Ausgabe für die fehlende Klasse geben.
Mogsie
1
Vielen Dank, dass Sie es ausprobiert haben, auch wenn das Ergebnis enttäuschend ist. (PS Ich habe seitdem herausgefunden, dass -verbose:class:jnidas falsch ist: Man muss zwei separate Optionen angeben : -verbose:class -verbose:jni.)
PJTraill
2
Der letzte Satz * 1.000.000: Wenn Sie also jemals ein NCDFE ohne Grundursache sehen, müssen Sie prüfen, ob Sie bis zum ersten Laden der Klasse zurückverfolgen können, um die Fehlerursache zu finden.
Batwad
20

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

ClassNotFoundException: tritt auf, wenn der Klassenladeprogramm die erforderliche Klasse im Klassenpfad nicht finden konnte. Grundsätzlich sollten Sie also Ihren Klassenpfad überprüfen und die Klasse in den Klassenpfad einfügen.

NoClassDefFoundError: Dies ist schwieriger zu debuggen und den Grund zu finden. Dies wird ausgelöst, wenn zur Kompilierungszeit die erforderlichen Klassen vorhanden sind, zur Laufzeit jedoch die Klassen geändert oder entfernt werden oder die statische Initialisierung der Klasse Ausnahmen auslöst. Dies bedeutet, dass die Klasse, die geladen wird, im Klassenpfad vorhanden ist, aber eine der Klassen, die von dieser Klasse benötigt werden, vom Compiler entweder entfernt oder nicht geladen werden konnte. Sie sollten also die Klassen sehen, die von dieser Klasse abhängig sind.

Beispiel :

public class Test1
{
}


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

}

Wenn Sie nun nach dem Kompilieren beider Klassen die Datei Test1.class löschen und die Testklasse ausführen, wird sie ausgelöst

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: Wird ausgelöst, wenn eine Anwendung versucht, eine Klasse über ihren Namen zu laden, aber keine Definition für die Klasse mit dem angegebenen Namen gefunden wurde.

NoClassDefFoundError: Wird ausgelöst, wenn die Java Virtual Machine versucht, die Definition einer Klasse zu laden, und keine Definition der Klasse gefunden werden konnte.

KingFeming
quelle
Was ist mit der Ausführung der JVM mit -verboseoder einer ähnlichen Option, abhängig von der jeweiligen JVM? Wahrscheinlich -verbose:class, vielleicht -verbose:class:jnibei Verwendung von JNI, aber ich bin mir über die Syntax nicht sicher.
PJTraill
-verbose:class:jniist falsch, aber Sie können zwei separate Optionen übergeben : -verbose:class -verbose:jni.
PJTraill
15

Was ist der Grund, warum jeder von ihnen und jeder Denkprozess zum Umgang mit solchen Fehlern kommt?

Sie sind eng miteinander verwandt. A ClassNotFoundExceptionwird ausgelöst, wenn Java nach einer bestimmten Klasse mit Namen gesucht hat und diese nicht erfolgreich laden konnte. A NoClassDefFoundErrorwird ausgelöst, wenn Java nach einer Klasse gesucht hat, die mit einem vorhandenen Code verknüpft war, diese aber aus dem einen oder anderen Grund nicht finden konnte (z. B. falscher Klassenpfad, falsche Version von Java, falsche Version einer Bibliothek), und ist äußerst fatal wie es anzeigt, dass etwas schlecht gelaufen ist.

Wenn Sie einen C-Hintergrund haben, ist ein CNFE wie ein Fehler bei dlopen()/ dlsym()und ein NCDFE ist ein Problem mit dem Linker. Im zweiten Fall sollten die betreffenden Klassendateien niemals in der Konfiguration kompiliert worden sein, in der Sie sie verwenden möchten.

Donal Fellows
quelle
11

Beispiel 1:

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

Wenn com/example/Class1in keinem der Klassenpfade vorhanden ist, wird es ausgelöst ClassNotFoundException.

Beispiel 2:

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

Wenn com/example/Class2es beim Kompilieren von B vorhanden war, aber während der Ausführung nicht gefunden wurde, wird es ausgelöst NoClassDefFoundError.

Beides sind Laufzeitausnahmen.

Dinesh
quelle
9

ClassNotFoundException wird ausgelöst, wenn versucht wird, die Klasse durch Referenzieren über einen String zu laden. Beispielsweise ist der Parameter in in Class.forName () ein String, und dies erhöht das Potenzial, dass ungültige Binärnamen an den Klassenladeprogramm übergeben werden.

Die ClassNotFoundException wird ausgelöst, wenn ein möglicherweise ungültiger Binärname auftritt. Wenn der Klassenname beispielsweise das Zeichen '/' hat, müssen Sie eine ClassNotFoundException erhalten. Es wird auch ausgelöst, wenn die direkt referenzierte Klasse im Klassenpfad nicht verfügbar ist.

Auf der anderen Seite wird NoClassDefFoundError ausgelöst

  • Wenn die tatsächliche physische Darstellung der Klasse - die .class-Datei nicht verfügbar ist,
  • oder die Klasse wurde bereits in einen anderen Klassenladeprogramm geladen (normalerweise hätte ein übergeordneter Klassenladeprogramm die Klasse geladen und daher kann die Klasse nicht erneut geladen werden),
  • oder wenn eine inkompatible Klassendefinition gefunden wurde - der Name in der Klassendatei stimmt nicht mit dem angeforderten Namen überein,
  • oder (am wichtigsten) wenn eine abhängige Klasse nicht gefunden und geladen werden kann. In diesem Fall wurde die direkt referenzierte Klasse möglicherweise gefunden und geladen, aber die abhängige Klasse ist nicht verfügbar oder kann nicht geladen werden. Dies ist ein Szenario, in dem die direkt referenzierte Klasse über Class.forName oder gleichwertige Methoden geladen werden kann. Dies weist auf einen Verbindungsfehler hin.

Kurz gesagt, ein NoClassDefFoundError wird normalerweise für new () -Anweisungen oder Methodenaufrufe ausgelöst, die eine zuvor fehlende Klasse laden (im Gegensatz zum stringbasierten Laden von Klassen für ClassNotFoundException), wenn der Klassenladeprogramm die Klassendefinition nicht finden oder laden kann ( s).

Schließlich liegt es an der ClassLoader-Implementierung, eine Instanz von ClassNotFoundException auszulösen, wenn eine Klasse nicht geladen werden kann. Die meisten benutzerdefinierten Classloader-Implementierungen führen dies aus, da sie den URLClassLoader erweitern. Normalerweise werfen Klassenlader keinen NoClassDefFoundError explizit auf eine der Methodenimplementierungen. Diese Ausnahme wird normalerweise von der JVM im HotSpot-Compiler und nicht vom Klassenlader selbst ausgelöst.

Vineet Reynolds
quelle
Upvote für die Erwähnung "Der Name in der Klassendatei stimmt nicht mit dem angeforderten Namen überein". Dies ist eine recht häufige Ursache.
Marquis von Lorne
8

Unterschied zwischen ClassNotFoundException und NoClassDefFoundError

Geben Sie hier die Bildbeschreibung ein

Lawakush Kurmi
quelle
Nicht kristallklar. "Im Klassenpfad nicht aktualisiert" ist vage / ungenau. Dies ist über die entweder die JAR nicht in der Gegenwart in dem Classpath, oder die falsche Version der JAR auf dem Classpath zu sein. Und Rechtschreibfehler. Und (seufz) da Sie Ihre Informationen als funky Grafik gepostet haben, können wir dies nicht beheben.
Stephen C
8

Mit den Namen selbst können wir leicht einen identifizieren Exceptionund einen anderen von Error.

Ausnahme: Ausnahmen treten während der Ausführung des Programms auf. Ein Programmierer kann diese Ausnahme behandeln, indem er den catch-Block versucht. Wir haben zwei Arten von Ausnahmen. Überprüfte Ausnahme, die zur Kompilierungszeit ausgelöst wird. Laufzeitausnahmen, die zur Laufzeit ausgelöst werden, treten normalerweise aufgrund einer schlechten Programmierung auf.

Fehler: Dies sind überhaupt keine Ausnahmen, es liegt außerhalb des Bereichs des Programmierers. Diese Fehler werden normalerweise von JVM ausgelöst.


Geben Sie hier die Bildbeschreibung ein Bildquelle

Unterschied:

ClassNotFoundException:

  • Class - Loader nicht zu überprüfen , eine Klasse Bytecode wir schon erwähnt , in Verbindung Phase der Klasse Laden Subsystem wir bekommen ClassNotFoundException.
  • ClassNotFoundExceptionist eine aktivierte Ausnahme, die direkt von der java.lang.ExceptionKlasse abgeleitet wurde und für die Sie eine explizite Behandlung bereitstellen müssen
  • ClassNotFoundExceptionwird angezeigt, wenn explizit geladen wirdWird angezeigt Klasse geladen wird, indem der Name der Klasse zur Laufzeit mit ClassLoader.loadClass (), Class.forName () und ClassLoader.findSystemClass () angegeben wird.

NoClassDefFoundError:

  • Der Klassenlader löst die Referenzen einer Klasse in der Link-Phase des Klassenlade-Subsystems, das wir erhalten, nicht aufNoClassDefFoundError .
  • NoClassDefFoundError ist ein Fehler abgeleitet von LinkageError Klasse , der verwendet wird, um Fehlerfälle anzuzeigen, bei denen eine Klasse von einer anderen Klasse abhängig ist und diese Klasse nach der Kompilierung inkompatibel geändert wurde.
  • NoClassDefFoundErrorist ein Ergebnis des impliziten Ladens einer Klasse aufgrund eines Methodenaufrufs dieser Klasse oder eines Variablenzugriffs.

Ähnlichkeiten:

  • Beide NoClassDefFoundErrorundClassNotFoundException stehen im Zusammenhang mit der Nichtverfügbarkeit einer Klasse zur Laufzeit.
  • Beide ClassNotFoundExceptionund NoClassDefFoundErrorbeziehen sich auf den Java-Klassenpfad.
Premraj
quelle
3

Angesichts der Class Loader-Sussystem-Aktionen:

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

Dies ist ein Artikel, der mir sehr geholfen hat, den Unterschied zu verstehen: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html

Wenn beim Laden der Klasse ein Fehler auftritt, eine Instanz einer Unterklasse von LinkageError an einer Stelle im Programm ausgelöst werden, die (direkt oder indirekt) die zu ladende Klasse oder Schnittstelle verwendet.

Wenn die Java Virtual Machine jemals versucht, eine Klasse C während der Überprüfung (§5.4.1) oder Auflösung (§5.4.3) (aber nicht der Initialisierung (§5.5)) und des Klassenladeprogramms zu laden, mit dem das Laden von C initiiert wird Wenn eine Instanz von ClassNotFoundException ausgelöst wird , muss die Java Virtual Machine eine Instanz von NoClassDefFoundError auslösen, deren Ursache die Instanz von ClassNotFoundException ist .

Eine ClassNotFoundException ist also eine Hauptursache für NoClassDefFoundError .
Und ein NoClassDefFoundError ist ein Sonderfall eines Typladefehlers , der im Verknüpfungsschritt auftritt .

Anton Shchastnyi
quelle
2

Fügen Sie einen möglichen Grund in der Praxis hinzu:

  • ClassNotFoundException: Wie Cletus sagte, verwenden Sie die Schnittstelle, während sich die geerbte Klasse der Schnittstelle nicht im Klassenpfad befindet. ZB Service Provider Pattern (oder Service Locator) ) versuchen, eine nicht vorhandene Klasse zu finden
  • NoClassDefFoundError: Die angegebene Klasse wurde gefunden, während die Abhängigkeit der angegebenen Klasse nicht gefunden wurde

In der Praxis wird der Fehler möglicherweise stillschweigend ausgelöst , z. B. wenn Sie eine Timer-Aufgabe senden und in der Timer-Aufgabe einen Fehler auslösen , während Ihr Programm in den meisten Fällen nur die Ausnahme abfängt . Dann wird die Timer- Hauptschleife ohne Informationen beendet. Ein ähnlicher Fehler wie bei NoClassDefFoundError ist ExceptionInInitializerError , wenn Ihr statischer Initialisierer oder der Initialisierer für eine statische Variable eine Ausnahme auslöst .

leef
quelle
1

ClassNotFoundException ist eine Ausnahme, die auftritt, wenn JVM wird, eine Klasse anhand ihres Zeichenfolgennamens mit den Methoden Class.forName () oder ClassLoader.findSystemClass () oder ClassLoader.loadClass () zu laden, und die erwähnte Klasse nicht im Klassenpfad gefunden wird.

Meistens tritt diese Ausnahme auf, wenn Sie versuchen, eine Anwendung auszuführen, ohne den Klassenpfad mit den erforderlichen JAR-Dateien zu aktualisieren. Zum Beispiel haben Sie diese Ausnahme möglicherweise gesehen, als Sie den JDBC-Code für die Verbindung mit Ihrer Datenbank ieMySQL ausgeführt haben, aber Ihr Klassenpfad verfügt nicht über JAR.

NoClassDefFoundError Fehler tritt auf, wenn JVM versucht, eine bestimmte Klasse zu laden, die Teil Ihrer Codeausführung ist (als Teil eines normalen Methodenaufrufs oder als Teil der Erstellung einer Instanz mit dem neuen Schlüsselwort) und diese Klasse in Ihrem Klassenpfad nicht vorhanden ist, aber war Zur Kompilierungszeit vorhanden, da Sie Ihr Programm kompilieren müssen, um es auszuführen. Wenn Sie versuchen, eine Klasse zu verwenden, die nicht vorhanden ist, führt der Compiler zu einem Kompilierungsfehler.

Unten ist die kurze Beschreibung

Geben Sie hier die Bildbeschreibung ein

Weitere Informationen finden Sie unter Alles über ClassNotFoundException gegen NoClassDefFoundError .

Naresh Joshi
quelle
0

Ich erinnere mich immer wieder an Folgendes, wenn ich mich aktualisieren muss

ClassNotFoundException

Klassenhierarchie

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

Beim Debuggen

  1. Erforderliches Glas, Klasse fehlt im Klassenpfad.
  2. Stellen Sie sicher, dass sich alle erforderlichen Jars im Klassenpfad von jvm befinden.

NoClassDefFoundError

Klassenhierarchie

NoClassDefFoundError extends LinkageError  extends Error extends Throwable

Beim Debuggen

  1. Problem beim dynamischen Laden einer Klasse, die ordnungsgemäß kompiliert wurde
  2. Problem mit statischen Blöcken, Konstruktoren, init () -Methoden der abhängigen Klasse und der tatsächliche Fehler wird von mehreren Ebenen umbrochen [insbesondere wenn Sie spring verwenden, wird der Ruhezustand im Ruhezustand umbrochen und Sie erhalten NoClassDefError]
  3. Wenn Sie "ClassNotFoundException" unter einem statischen Block einer abhängigen Klasse gegenüberstehen
  4. Problem mit Klassenversionen. Dies geschieht, wenn Sie zwei Versionen v1, v2 derselben Klasse unter verschiedenen JAR / Paketen haben, die erfolgreich mit v1 kompiliert wurden, und v2 zur Laufzeit geladen wird, die nicht über die relevanten Methoden / Vars verfügt. Diese Ausnahme wird angezeigt. [Ich habe dieses Problem einmal behoben, indem ich das Duplikat der log4j-bezogenen Klasse unter mehreren Jars entfernt habe, die im Klassenpfad angezeigt wurden.]
Sankarganesh Eswaran
quelle
-1

ClassNotFoundException und NoClassDefFoundError treten auf, wenn eine bestimmte Klasse zur Laufzeit nicht gefunden wird. Sie treten jedoch in verschiedenen Szenarien auf.

ClassNotFoundException ist eine Ausnahme, die auftritt, wenn Sie versuchen, eine Klasse zur Laufzeit mit den Methoden Class.forName () oder loadClass () zu laden. Die genannten Klassen werden im Klassenpfad nicht gefunden.

    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 ist ein Fehler, der auftritt, wenn eine bestimmte Klasse zur Kompilierungszeit vorhanden ist, aber zur Laufzeit fehlt.

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

Wenn Sie das obige Programm kompilieren, werden zwei .class-Dateien generiert. Eine ist A. Klasse und eine andere ist B. Klasse. Wenn Sie die A.class-Datei entfernen und die B.class-Datei ausführen, löst Java Runtime System NoClassDefFoundError wie folgt aus:

    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)
Neeraj Gahlawat
quelle