Was ist der Unterschied zwischen NoClassDefFoundError
und 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:
- Pakete, die
build.xml
für die Client-Seite des Codes nicht enthalten sind - Der Laufzeitklassenpfad fehlt für die neuen Jars, die wir verwenden
- 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.
-verbose
(z. B.-verbose:class -verbose:jni
) zu betreiben - aber Mogsie berichtet unter ihrer Antwort, dass dies keine zusätzlichen nützlichen Informationen liefert :(Antworten:
Der Unterschied zu den Java-API-Spezifikationen ist wie folgt.
Für
ClassNotFoundException
:Für
NoClassDefFoundError
:Es scheint also, dass dies
NoClassDefFoundError
auftritt, wenn die Quelle erfolgreich kompiliert wurde, aber zur Laufzeit die erforderlichenclass
Dateien nicht gefunden wurden. Dies kann bei der Verteilung oder Produktion von JAR-Dateien vorkommen, bei denen nicht alle erforderlichenclass
Dateien enthalten waren.Was
ClassNotFoundException
scheint 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
Error
und der andere ein istException
. MitNoClassDefFoundError
ist einError
und 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, daclass
Dateien 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
ClassNotFoundException
einException
, 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 .quelle
NoClassDefFoundError
tritt 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.Error
und der andere ist einException
. :)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.NoClassDefFoundError
mitjava.lang.ClassNotFoundException
aber es gibt einen wichtigen Unterschied. Zum Beispiel eine Ausnahme (ein Fehler, der wirklich dajava.lang.NoClassDefFoundError
eine Unterklasse von java.lang.Error ist) wiebedeutet 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.
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.
quelle
NoClassDefFoundError
ist 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.ClassNotFoundException
ist 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 vonloadClass()
oderClass.forName()
.quelle
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:
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 . a
Es 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:
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.
quelle
-verbose
oder einer ähnlichen Option, abhängig von der jeweiligen JVM? Wahrscheinlich-verbose:class
, vielleicht-verbose:class:jni
bei 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.-verbose:class
noch-verbose:jni
zusätzliche Ausgabe für die fehlende Klasse geben.-verbose:class:jni
das falsch ist: Man muss zwei separate Optionen angeben :-verbose:class -verbose:jni
.)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 :
Wenn Sie nun nach dem Kompilieren beider Klassen die Datei Test1.class löschen und die Testklasse ausführen, wird sie ausgelöst
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.quelle
-verbose
oder einer ähnlichen Option, abhängig von der jeweiligen JVM? Wahrscheinlich-verbose:class
, vielleicht-verbose:class:jni
bei Verwendung von JNI, aber ich bin mir über die Syntax nicht sicher.-verbose:class:jni
ist falsch, aber Sie können zwei separate Optionen übergeben :-verbose:class -verbose:jni
.Sie sind eng miteinander verwandt. A
ClassNotFoundException
wird ausgelöst, wenn Java nach einer bestimmten Klasse mit Namen gesucht hat und diese nicht erfolgreich laden konnte. ANoClassDefFoundError
wird 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.quelle
Beispiel 1:
Wenn
com/example/Class1
in keinem der Klassenpfade vorhanden ist, wird es ausgelöstClassNotFoundException
.Beispiel 2:
Wenn
com/example/Class2
es beim Kompilieren von B vorhanden war, aber während der Ausführung nicht gefunden wurde, wird es ausgelöstNoClassDefFoundError
.Beides sind Laufzeitausnahmen.
quelle
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
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.
quelle
Unterschied zwischen ClassNotFoundException und NoClassDefFoundError
quelle
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.
Bildquelle
Unterschied:
ClassNotFoundException:
ClassNotFoundException
.ClassNotFoundException
ist eine aktivierte Ausnahme, die direkt von derjava.lang.Exception
Klasse abgeleitet wurde und für die Sie eine explizite Behandlung bereitstellen müssenClassNotFoundException
wird 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:
NoClassDefFoundError
.NoClassDefFoundError
ist ein Fehler abgeleitet vonLinkageError
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.NoClassDefFoundError
ist ein Ergebnis des impliziten Ladens einer Klasse aufgrund eines Methodenaufrufs dieser Klasse oder eines Variablenzugriffs.Ähnlichkeiten:
NoClassDefFoundError
undClassNotFoundException
stehen im Zusammenhang mit der Nichtverfügbarkeit einer Klasse zur Laufzeit.ClassNotFoundException
undNoClassDefFoundError
beziehen sich auf den Java-Klassenpfad.quelle
Angesichts der Class Loader-Sussystem-Aktionen:
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
Eine ClassNotFoundException ist also eine Hauptursache für NoClassDefFoundError .
Und ein NoClassDefFoundError ist ein Sonderfall eines Typladefehlers , der im Verknüpfungsschritt auftritt .
quelle
Fügen Sie einen möglichen Grund in der Praxis hinzu:
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 .
quelle
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
Weitere Informationen finden Sie unter Alles über ClassNotFoundException gegen NoClassDefFoundError .
quelle
Ich erinnere mich immer wieder an Folgendes, wenn ich mich aktualisieren muss
ClassNotFoundException
Klassenhierarchie
Beim Debuggen
NoClassDefFoundError
Klassenhierarchie
Beim Debuggen
quelle
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.
NoClassDefFoundError ist ein Fehler, der auftritt, wenn eine bestimmte Klasse zur Kompilierungszeit vorhanden ist, aber zur Laufzeit fehlt.
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:
quelle