Ich erhalte eine, NoClassDefFoundError
wenn ich meine Java-Anwendung ausführe. Was ist typischerweise die Ursache dafür?
java
noclassdeffounderror
John Meagher
quelle
quelle
Antworten:
Dies wird verursacht, wenn es eine Klassendatei gibt, von der Ihr Code abhängt und die zur Kompilierungszeit vorhanden ist, aber zur Laufzeit nicht gefunden wird. Suchen Sie nach Unterschieden in Ihren Erstellungszeit- und Laufzeitklassenpfaden.
quelle
Es ist zwar möglich, dass dies auf eine Klassenübereinstimmung zwischen Kompilierungszeit und Laufzeit zurückzuführen ist, dies ist jedoch nicht unbedingt der Fall.
In diesem Fall ist es wichtig, zwei oder drei verschiedene Ausnahmen im Kopf zu behalten:
java.lang.ClassNotFoundException
Diese Ausnahme gibt an, dass die Klasse nicht im Klassenpfad gefunden wurde. Dies zeigt an, dass wir versucht haben, die Klassendefinition zu laden, und die Klasse im Klassenpfad nicht vorhanden war.java.lang.NoClassDefFoundError
Diese Ausnahme gibt an, dass die JVM in ihrer internen Klassendefinitionsdatenstruktur nach der Definition einer Klasse gesucht und diese nicht gefunden hat. Dies unterscheidet sich von der Aussage, dass es nicht aus dem Klassenpfad geladen werden konnte. Normalerweise bedeutet dies, dass wir zuvor versucht haben, eine Klasse aus dem Klassenpfad zu laden, dies jedoch aus irgendeinem Grund fehlgeschlagen ist. Jetzt versuchen wir, die Klasse erneut zu verwenden (und müssen sie daher laden, da sie beim letzten Mal fehlgeschlagen ist). Ich werde nicht einmal versuchen, es zu laden, weil wir es früher nicht geladen haben (und vernünftigerweise vermuten, dass wir wieder scheitern würden). Der frühere Fehler kann eine ClassNotFoundException oder ein ExceptionInInitializerError sein (was auf einen Fehler im statischen Initialisierungsblock hinweist) oder eine beliebige Anzahl anderer Probleme. Der Punkt ist, dass ein NoClassDefFoundError nicht unbedingt ein Klassenpfadproblem ist.quelle
Error: Could not find or load main class
wird es in welche Fehlerkategorie eingestuft?Hier ist der Code zur Veranschaulichung
java.lang.NoClassDefFoundError
. Weitere Informationen finden Sie in Jareds Antwort .NoClassDefFoundErrorDemo.java
SimpleCalculator.java
quelle
SimpleCalculator
nach der Division durch Null gespeichert ? Hat jemand einen Verweis auf die offizielle Dokumentation für dieses Verhalten?new SimpleCalculator()
Aufruf erhalten Sie einen ExceptionInInitializerError mit einem von ArithmeticException verursachten Fehler. Beim zweiten Aufruf erhaltennew SimpleCalculator()
Sie einen NoClassDefFoundError, der so rein ist wie jeder andere. Der Punkt ist, dass Sie einen NoClassDefFoundError aus einem anderen Grund als SimpleCalculator.class erhalten können, der sich zur Laufzeit nicht im Klassenpfad befindet.NoClassDefFoundError In Java
Definition:
Java Virtual Machine kann zur Laufzeit keine bestimmte Klasse finden, die zur Kompilierungszeit verfügbar war.
Wenn eine Klasse während der Kompilierungszeit vorhanden war, aber zur Laufzeit nicht im Java-Klassenpfad verfügbar war.
Beispiele:
Ein einfaches Beispiel für NoClassDefFoundError ist, dass die Klasse zu einer fehlenden JAR-Datei gehört oder dass JAR nicht zum Klassenpfad hinzugefügt wurde oder dass der Name von jar von jemandem geändert wurde, wie in meinem Fall einer meiner Kollegen tibco.jar in tibco_v3.jar geändert hat und das Programm ist Fehler mit java.lang.NoClassDefFoundError und ich haben uns gefragt, was los ist.
Versuchen Sie einfach, die explizite Option -classpath mit dem Klassenpfad auszuführen, von dem Sie glauben, dass er funktioniert. Wenn dies funktioniert, ist dies ein sicheres kurzes Zeichen dafür, dass jemand den Java-Klassenpfad überschreibt.
Mögliche Lösungen:
Ressourcen:
3 Möglichkeiten, NoClassDefFoundError zu lösen
java.lang.NoClassDefFoundError Problemmuster
quelle
Ich habe festgestellt, dass manchmal ein NoClassDefFound-Fehler auftritt, wenn Code mit einer inkompatiblen Version der zur Laufzeit gefundenen Klasse kompiliert wird. Die spezifische Instanz, an die ich mich erinnere, ist die Apache-Achsenbibliothek. Es gab tatsächlich 2 Versionen in meinem Laufzeitklassenpfad und es wurde die veraltete und inkompatible Version und nicht die richtige Version gefunden, was einen NoClassDefFound-Fehler verursachte. Dies war in einer Befehlszeilen-App, in der ich einen ähnlichen Befehl verwendete.
Ich konnte es dazu bringen, die richtige Version zu finden, indem ich Folgendes verwendete:
quelle
Dies ist die beste Lösung, die ich bisher gefunden habe.
Angenommen, wir haben ein Paket
org.mypackage
mit den Klassen:und die Dateien, die dieses Paket definieren, werden physisch im Verzeichnis
D:\myprogram
(unter Windows) oder/home/user/myprogram
(unter Linux) gespeichert .Die Dateistruktur sieht folgendermaßen aus:
Wenn wir Java aufrufen, geben wir den Namen der auszuführenden Anwendung an :
org.mypackage.HelloWorld
. Wir müssen Java jedoch auch mitteilen, wo nach den Dateien und Verzeichnissen gesucht werden soll, die unser Paket definieren. Um das Programm zu starten, müssen wir den folgenden Befehl verwenden:quelle
Ich habe Spring Framework mit Maven verwendet und diesen Fehler in meinem Projekt behoben.
In der Klasse ist ein Laufzeitfehler aufgetreten. Ich habe eine Eigenschaft als Ganzzahl gelesen, aber als sie den Wert aus der Eigenschaftendatei las, war ihr Wert doppelt so hoch.
Spring gab mir keine vollständige Stapelverfolgung darüber, auf welcher Zeile die Laufzeit fehlgeschlagen ist. Es sagte einfach
NoClassDefFoundError
. Aber als ich es als native Java-Anwendung ausführte (aus MVC herausnahm), gab es an,ExceptionInInitializerError
welche die wahre Ursache war und wie ich den Fehler verfolgte.Die Antwort von @ xli gab mir einen Einblick in das, was in meinem Code möglicherweise falsch ist.
quelle
NoClassDefFoundError
wurde tatsächlich durch verursachtExceptionInInitalizerError
, was durch verursacht wurdeDateTimeParseException
). Es ist ein bisschen irreführend, nicht wahr? Ich weiß, dass sie wahrscheinlich ihre Gründe hatten, es so zu machen, aber es wäre so schön, zumindest einen kleinen Hinweis zu haben, der dasNoClassDefFoundError
Ergebnis einer anderen Ausnahme war, ohne dass man darauf schließen musste. Nur nochExceptionInInitializerError
einmal zu werfen wäre viel klarer. Manchmal ist die Verbindung zwischen den beiden nicht so offensichtlich.Ich erhalte NoClassFoundError, wenn vom Runtime Class Loader geladene Klassen nicht auf Klassen zugreifen können, die bereits vom Java Rootloader geladen wurden. Da sich die verschiedenen Klassenlader in verschiedenen Sicherheitsdomänen befinden (laut Java), erlaubt die JVM nicht, dass Klassen, die bereits vom Rootloader geladen wurden, im Adressraum des Laufzeitladers aufgelöst werden.
Führen Sie Ihr Programm mit 'java -javaagent: tracer.jar [IHRE Java-ARGS]' aus.
Es wird eine Ausgabe erzeugt, die die geladene Klasse und die Loader-Umgebung zeigt, die die Klasse geladen hat. Es ist sehr hilfreich zu verfolgen, warum eine Klasse nicht aufgelöst werden kann.
quelle
Ein interessanter Fall, in dem Sie möglicherweise viel sehen,
NoClassDefFoundErrors
ist, wenn Sie:throw
aRuntimeException
imstatic
Block Ihrer KlasseExample
Example
NoClassDefError
wird zusammen mitExceptionInInitializerError
dem statischen Block geworfenRuntimeException
.Dies ist besonders wichtig, wenn Sie
NoClassDefFoundErrors
in Ihren EINHEITSTESTS sehen .In gewisser Weise "teilen" Sie die
static
Blockausführung zwischen Tests, aber die InitialeExceptionInInitializerError
befindet sich nur in einem Testfall. Der erste, der die problematischeExample
Klasse verwendet. Andere Testfälle, die dieExample
Klasse verwenden, werden nur geworfenNoClassDefFoundErrors
.quelle
Die folgende Technik hat mir oft geholfen:
Dabei ist TheNoDefFoundClass die Klasse, die möglicherweise "verloren" geht, weil Sie eine ältere Version derselben Bibliothek bevorzugen, die von Ihrem Programm verwendet wird. Dies ist am häufigsten der Fall, wenn die Client-Software in einem dominanten Container bereitgestellt wird, der mit eigenen Klassenladern und Tonnen alter Versionen der beliebtesten Bibliotheken ausgestattet ist.
quelle
Wenn Sie Code generiert haben (EMF usw.), kann es zu viele statische Initialisierer geben, die den gesamten Stapelspeicher belegen.
Siehe Frage zum Stapelüberlauf. Wie kann die Java-Stapelgröße erhöht werden? .
quelle
Ich habe mein Problem behoben, indem ich die preDexLibraries für alle Module deaktiviert habe:
quelle
NoClassDefFoundError
Dies kann auch auftreten, wenn ein statischer Initialisierer versucht, ein Ressourcenpaket zu laden, das zur Laufzeit nicht verfügbar ist, z. B. eine Eigenschaftendatei, die die betroffene Klasse aus demMETA-INF
Verzeichnis zu laden versucht , aber nicht vorhanden ist. Wenn Sie nicht fangenNoClassDefFoundError
, können Sie manchmal nicht die vollständige Stapelverfolgung sehen. Um dies zu überwinden, können Sie vorübergehend einecatch
Klausel verwenden fürThrowable
:quelle
for example a properties file that the affected class tries to load from the META-INF directory
. Dies ist mir tatsächlich passiert und ich konnte das Problem beheben,NoClassDefFoundError
indem ich die fehlende Eigenschaftendatei hinzufügte. Ich habe diese Antwort genau hinzugefügt, weil man diesen Fehler unter den genannten Umständen nicht erwarten würde.static
Initialisierung zu laden ... was eine ungeprüfte Ausnahme auslöste und die Klasse init auslöste Versagen. Jede ungeprüfte Ausnahme, die sich aus der statischen Initialisierung ausbreitet, würde dies tun.static
liege (dh dies liegt nicht an einer fehlgeschlagenen Initialisierung), wäre ich an einem tatsächlichen Beispiel (z. B. einem MCVE) interessiert, das das Verhalten demonstriert.Ich habe diesen Fehler erhalten, als ich meinem Projekt die Maven-Abhängigkeit eines anderen Moduls hinzufügte. Das Problem wurde schließlich durch Hinzufügen
-Xss2m
zur JVM-Option meines Programms behoben (seit JDK5.0 ist es standardmäßig ein Megabyte). Es wird angenommen, dass das Programm nicht genügend Stapel hat, um die Klasse zu laden.quelle
Wenn jemand aufgrund eines
java.lang.NoClassDefFoundError: org/apache/log4j/Logger
Fehlers hierher kommt , wurde er in meinem Fall erstellt, weil ich log4j 2 verwendet habe (aber nicht alle mitgelieferten Dateien hinzugefügt habe), und einige Abhängigkeitsbibliotheken haben log4j 1 verwendet. Die Lösung bestand darin, Log4j hinzuzufügen 1.x Bridge: daslog4j-1.2-api-<version>.jar
mit log4j gelieferte JAR 2. Weitere Informationen in der log4j 2- Migration .quelle
Zwei verschiedene Checkout-Kopien desselben Projekts
In meinem Fall war das Problem die Unfähigkeit von Eclipse, zwischen zwei verschiedenen Kopien desselben Projekts zu unterscheiden. Ich habe einen auf Trunk gesperrt (SVN-Versionskontrolle) und den anderen, der jeweils in einem Zweig arbeitet. Ich habe eine Änderung in der Arbeitskopie als JUnit-Testfall ausprobiert, bei der eine private innere Klasse extrahiert wurde, um eine öffentliche Klasse für sich zu sein, und während sie funktionierte, öffne ich die andere Kopie des Projekts, um mich nach einer anderen umzusehen Teil des Codes, der geändert werden musste. Irgendwann
NoClassDefFoundError
tauchten die auf und beschwerten sich, dass die private innere Klasse nicht da war; Durch Doppelklicken in den Stack-Trace gelangte ich zur Quelldatei in der falschen Projektkopie.Durch Schließen der Trunk-Kopie des Projekts und erneutes Ausführen des Testfalls wurde das Problem behoben.
quelle
Dieser Fehler kann durch ungeprüfte Java-Versionsanforderungen verursacht werden.
In meinem Fall konnte ich diesen Fehler beim Erstellen eines hochkarätigen Open-Source-Projekts beheben, indem ich mit SDKMAN von Java 9 auf Java 8 wechselte! .
Führen Sie dann eine Neuinstallation wie unten beschrieben durch.
Wenn Sie Maven als Build-Tool verwenden, ist es manchmal hilfreich - und in der Regel erfreulich -, einen sauberen Build mit deaktiviertem Test durchzuführen .
Nachdem alles erstellt und installiert wurde, können Sie die Tests ausführen.
quelle
Ich habe NoClassDefFound-Fehler erhalten, als ich keine Klasse auf der Registerkarte "Bestellen und Exportieren" im Java-Erstellungspfad meines Projekts exportiert habe. Stellen Sie sicher, dass auf der Registerkarte "Bestellen und Exportieren" ein Häkchen für alle Abhängigkeiten gesetzt ist, die Sie dem Erstellungspfad des Projekts hinzufügen. Siehe Eclipse-Warnung: XXXXXXXXXXX.jar wird nicht exportiert oder veröffentlicht. Es kann zur Laufzeit ClassNotFoundExceptions kommen .
quelle
Dies kann auch daran liegen, dass Sie die Codedatei von einer IDE mit einem bestimmten Paketnamen kopieren und versuchen möchten, sie über das Terminal auszuführen. Sie müssen zuerst den Paketnamen aus dem Code entfernen. Das passiert mir.
quelle
In meinem Fall wurde dieser Fehler aufgrund einer Nichtübereinstimmung in den JDK-Versionen angezeigt. Als ich versuchte, die Anwendung von Intelij aus auszuführen, funktionierte sie nicht, aber dann funktionierte es über die Befehlszeile. Dies liegt daran, dass Intelij versucht hat, es mit dem Java 11 JDK auszuführen, das eingerichtet wurde, aber in der Befehlszeile mit dem Java 8 JDK ausgeführt wurde. Nachdem ich diese Einstellung unter Datei> Projekteinstellung> Projekteinstellungen> Projekt-SDK geändert hatte, funktionierte sie für mich.
quelle
Alle sprechen hier über Java-Konfigurationsmaterial, JVM-Probleme usw. In meinem Fall hatte der Fehler überhaupt nichts mit diesen Themen zu tun und hatte einen sehr trivialen und leicht zu lösenden Grund: Ich hatte eine falsche Anmerkung an meinem Endpunkt in meinem Controller ( Spring Boot-Anwendung).
quelle
Ich hatte ein interessantes Problem mit NoClassDefFoundError in JavaEE, das mit Liberty Server zusammenarbeitet. Ich habe IMS-Ressourcenadapter verwendet und meine server.xml hatte bereits einen Ressourcenadapter für imsudbJXA.rar. Wenn ich einen neuen Adapter für imsudbXA.rar hinzufügte, wurde dieser Fehler beispielsweise für Objekte für DLIException, IMSConnectionSpec oder SQLInteractionSpec angezeigt. Ich konnte nicht herausfinden warum, aber ich habe es behoben, indem ich eine neue server.xml für meine Arbeit nur mit imsudbXA.rar erstellt habe. Ich bin sicher, dass die Verwendung mehrerer Ressourcenadapter in server.xml in Ordnung ist. Ich hatte einfach keine Zeit, mich damit zu befassen.
quelle
Java konnte die Klasse A zur Laufzeit nicht finden. Klasse A befand sich im Maven-Projekt ArtClient aus einem anderen Arbeitsbereich. Also habe ich ArtClient in mein Eclipse-Projekt importiert. Zwei meiner Projekte verwendeten ArtClient als Abhängigkeit. Ich habe die Bibliotheksreferenz für diese in eine Projektreferenz geändert (Erstellungspfad -> Erstellungspfad konfigurieren).
Und das Problem ist weg.
quelle
Ich hatte das gleiche Problem und war viele Stunden auf Lager.
Ich habe die Lösung gefunden. In meinem Fall wurde aufgrund dessen die statische Methode definiert. Die JVM kann kein anderes Objekt dieser Klasse erstellen.
Zum Beispiel,
quelle
Ich habe diese Meldung erhalten, nachdem ich zwei Dateien aus der SRC-Bibliothek entfernt hatte, und als ich sie zurückbrachte, wurde diese Fehlermeldung immer wieder angezeigt.
Meine Lösung war: Starten Sie Eclipse neu. Seitdem habe ich diese Nachricht nicht mehr gesehen :-)
quelle
Stellen Sie sicher, dass dies in
module:app
und übereinstimmtmodule:lib
:quelle
{s
und zwei}
). Kannst du das Reparieren?