Frage

Ich bekomme eine NoClassDefFoundError wenn ich meine Java-Anwendung ausführe.Was ist typischerweise die Ursache hierfür?

War es hilfreich?

Lösung

Dies wird verursacht, wenn es eine Klassendatei gibt, von der Ihr Code abhängt, und diese zur Kompilierungszeit vorhanden, aber zur Laufzeit nicht gefunden wird.Suchen Sie nach Unterschieden in Ihren Build-Zeit- und Laufzeit-Klassenpfaden.

Andere Tipps

Es ist zwar möglich, dass dies auf eine Nichtübereinstimmung des Klassenpfads zwischen der Kompilierungszeit und der 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:

  1. java.lang.ClassNotFoundException Diese Ausnahme weist darauf hin, dass die Klasse nicht im Klassenpfad gefunden wurde.Dies weist darauf hin, dass wir versucht haben, die Klassendefinition zu laden, und die Klasse im Klassenpfad nicht vorhanden war.

  2. java.lang.NoClassDefFoundError Diese Ausnahme weist darauf hin, dass die JVM in ihrer internen Klassendefinitionsdatenstruktur nach der Definition einer Klasse gesucht und diese nicht gefunden hat.Das ist etwas anderes als zu sagen, dass es nicht aus dem Klassenpfad geladen werden konnte.Normalerweise weist dies darauf hin, dass wir zuvor versucht haben, eine Klasse aus dem Klassenpfad zu laden, dies jedoch aus irgendeinem Grund fehlgeschlagen ist. Jetzt versuchen wir erneut, die Klasse zu verwenden (und müssen sie daher laden, da dies beim letzten Mal fehlgeschlagen ist), aber wir Wir werden nicht einmal versuchen, es zu laden, da wir es zuvor nicht geladen haben (und begründeten Verdacht haben, dass wir erneut scheitern würden).Der frühere Fehler könnte eine ClassNotFoundException oder ein ExceptionInInitializerError (was auf einen Fehler im statischen Initialisierungsblock hinweist) oder eine beliebige Anzahl anderer Probleme sein.Der Punkt ist, dass ein NoClassDefFoundError nicht unbedingt ein Klassenpfadproblem ist.

Hier ist der Code zur Veranschaulichung java.lang.NoClassDefFoundError.Bitte sehen Jareds Antwort für eine ausführliche Erklärung.

NoClassDefFoundErrorDemo.java

public class NoClassDefFoundErrorDemo {
    public static void main(String[] args) {
        try {
            // The following line would throw ExceptionInInitializerError
            SimpleCalculator calculator1 = new SimpleCalculator();
        } catch (Throwable t) {
            System.out.println(t);
        }
        // The following line would cause NoClassDefFoundError
        SimpleCalculator calculator2 = new SimpleCalculator();
    }

}

SimpleCalculator.java

public class SimpleCalculator {
    static int undefined = 1 / 0;
}

Ich habe festgestellt, dass ich manchmal einen NoClassDefFound-Fehler erhalte, wenn Code mit einer inkompatiblen Version der zur Laufzeit gefundenen Klasse kompiliert wird.Der konkrete Fall, an den ich mich erinnere, betrifft die Apache-Achsenbibliothek.Es gab tatsächlich zwei Versionen in meinem Laufzeitklassenpfad und es wurde die veraltete und inkompatible Version und nicht die richtige ausgewählt, was einen NoClassDefFound-Fehler verursachte.Dies geschah in einer Befehlszeilen-App, in der ich einen ähnlichen Befehl verwendete.

set classpath=%classpath%;axis.jar

Ich konnte es mithilfe von Folgendem dazu bringen, die richtige Version abzurufen:

set classpath=axis.jar;%classpath%;

NoClassDefFoundError In Java

Definition:

  1. Java Virtual Machine kann zur Laufzeit keine bestimmte Klasse finden, die zur Kompilierzeit verfügbar war.

  2. Wenn eine Klasse während der Kompilierungszeit vorhanden war, aber zur Laufzeit nicht im Java-Klassenpfad verfügbar war.

enter image description here

Beispiele:

  1. Die Klasse befindet sich nicht im Klassenpfad, es gibt keinen sicheren Weg, sie herauszufinden, aber oft können Sie einfach einen Blick darauf werfen, um System.getproperty("java.classpath") zu drucken, und der Klassenpfad wird von dort aus gedruckt, den Sie zumindest abrufen können eine Vorstellung von Ihrem tatsächlichen Laufzeitklassenpfad.
  2. Ein einfaches Beispiel für NoClassDefFoundError ist, dass die Klasse zu einer fehlenden JAR-Datei gehört oder JAR nicht zum Klassenpfad hinzugefügt wurde oder manchmal der Name des Jars von jemandem geändert wurde, wie in meinem Fall einer meiner Kollegen, der tibco.jar in tibco_v3.jar geändert hat, und das Programm ist Fehler bei java.lang.NoClassDefFoundError und ich habe mich gefragt, was los ist.

  3. Versuchen Sie einfach, die explizite Option -classpath mit dem Klassenpfad auszuführen, von dem Sie glauben, dass er funktioniert. Wenn er funktioniert, ist das ein sicheres kurzes Zeichen dafür, dass jemand den Java-Klassenpfad überschreibt.

  4. Berechtigungsprobleme für die JAR-Datei können in Java auch zu NoClassDefFoundError führen.
  5. Tippfehler bei der XML-Konfiguration können in Java auch zu NoClassDefFoundError führen.
  6. Wenn Ihre kompilierte Klasse, die in einem Paket definiert ist, beim Laden nicht im selben Paket vorhanden ist, wie im Fall von JApplet, wird in Java ein NoClassDefFoundError ausgelöst.

Mögliche Lösungen:

  1. Die Klasse ist im Java Classpath nicht verfügbar.
  2. Wenn Sie in einer J2EE-Umgebung arbeiten, kann die Sichtbarkeit der Klasse in mehreren Classloadern auch zu java.lang.NoClassDefFoundError führen. Eine ausführliche Erläuterung finden Sie im Abschnitt „Beispiele und Szenarios“.
  3. Suchen Sie in Ihrer Protokolldatei nach java.lang.ExceptionInInitializerError.NoClassDefFoundError aufgrund des Fehlers bei der statischen Initialisierung kommt recht häufig vor.
  4. Da NoClassDefFoundError eine Unterklasse von java.lang.LinkageError ist, kann es auch dazu kommen, dass eine seiner Abhängigkeiten wie die native Bibliothek möglicherweise nicht verfügbar ist.
  5. Jedes Startskript überschreibt die Umgebungsvariable Classpath.
  6. Möglicherweise führen Sie Ihr Programm mit dem Befehl jar aus und die Klasse wurde nicht im ClassPath-Attribut der Manifestdatei definiert.

Ressourcen:

3 Möglichkeiten, NoClassDefFoundError zu lösen

java.lang.NoClassDefFoundError Problemmuster

Dies ist das beste Lösung Habe ich bisher gefunden.

Angenommen, wir haben ein Paket namens org.mypackage enthält die Klassen:

  • HelloWorld (Hauptklasse)
  • SupportClass
  • UtilClass

und die Dateien, die dieses Paket definieren, werden physisch im Verzeichnis gespeichert D:\myprogram (unter Windows) oder /home/user/myprogram (unter Linux).

Die Dateistruktur sieht folgendermaßen aus:enter image description here

Wenn wir Java aufrufen, geben wir den Namen der auszuführenden Anwendung an: org.mypackage.HelloWorld.Allerdings müssen wir Java auch mitteilen, wo es nach den Dateien und Verzeichnissen suchen soll, die unser Paket definieren.Um das Programm zu starten, müssen wir also den folgenden Befehl verwenden:enter image description here

Ich habe verwendet Frühlingsrahmen mit Maven 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 hat mir keinen vollständigen Stack-Trace darüber gegeben, auf welcher Zeile die Laufzeit fehlgeschlagen ist.Es hieß einfach NoClassDefFoundError.Aber als ich es als native Java-Anwendung ausführte (aus MVC herausgenommen), gab es nach ExceptionInInitializerError was die wahre Ursache war und wie ich den Fehler aufspüren konnte.

Die Antwort von @xli gab mir Einblick, was in meinem Code möglicherweise falsch ist.

Ich erhalte NoClassFoundError, wenn vom Laufzeit-Klassenlader geladene Klassen nicht auf Klassen zugreifen können, die bereits vom Java-Rootloader geladen wurden.Da sich die verschiedenen Klassenlader in unterschiedlichen Sicherheitsdomänen befinden (je nach Java), lässt der JVM nicht zu, dass bereits vom Rootloader geladene Klassen im Adressraum des Laufzeitladers aufgelöst werden.

Führen Sie Ihr Programm mit „java -javaagent:tracer.jar [IHR 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, herauszufinden, warum eine Klasse nicht aufgelöst werden kann.

// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5

import java.lang.instrument.*;
import java.security.*;

// manifest.mf
// Premain-Class: ClassLoadTracer

// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class

// java -javaagent:tracer.jar  [...]

public class ClassLoadTracer 
{
    public static void premain(String agentArgs, Instrumentation inst) 
    {
        final java.io.PrintStream out = System.out;
        inst.addTransformer(new ClassFileTransformer() {
            public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

                String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
                out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);

                // dump stack trace of the thread loading class 
                Thread.dumpStack();

                // we just want the original .class bytes to be loaded!
                // we are not instrumenting it...
                return null;
            }
        });
    }
}

Lesen Sie dies besonders, wenn Sie es sehen NoClassDefFoundErrors in UNIT-TESTS...


Ein interessanter Fall, von dem Sie möglicherweise eine Menge sehen werden NoClassDefFoundErrors ist, wenn Sie:

  1. throw A RuntimeException im static Block Ihrer Klasse Example
  2. Fangen Sie es ab (oder wenn es einfach keine Rolle spielt, werfen Sie es in einen Testfall)
  3. Versuchen Sie, eine Instanz dieser Klasse zu erstellen Example

static class Example {
    static {
        thisThrowsRuntimeException();
    }
}

static class OuterClazz {

    OuterClazz() {
        try {
            new Example();
        } catch (Throwable ignored) { //simulating catching RuntimeException from static block
            // DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
        }

        new Example(); //this throws NoClassDefFoundError
    }
}

NoClassDefError wird begleitet von geworfen ExceptionInInitializerError aus dem statischen Block RuntimeException.


Dies ist besonders wichtig, wenn Sie sehen NoClassDefFoundErrors in deinem UNIT-TESTS.

In gewisser Weise „teilen“ Sie das static Blockausführung zwischen Tests, aber die anfängliche ExceptionInInitializerError wird nur in einem Testfall sein.Der erste, der die Problematik nutzt Example Klasse.Andere Testfälle, die das verwenden Example Klasse wird einfach werfen NoClassDefFoundErrors.

Falls Sie generierten Code (EMF usw.) haben, kann es zu viele statische Initialisierer geben, die den gesamten Stapelspeicher belegen.

Siehe Frage zum Stapelüberlauf Wie kann die Größe des Java-Stacks erhöht werden?.

Die folgende Technik hat mir oft geholfen:

System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());

Dabei ist TheNoDefFoundClass die Klasse, die möglicherweise aufgrund einer Präferenz für eine ältere Version derselben Bibliothek, die von Ihrem Programm verwendet wird, „verloren“ geht.Dies geschieht am häufigsten in Fällen, in denen die Client-Software in einem dominanten Container bereitgestellt wird, der mit seinen eigenen Klassenladern und Tonnen alter Versionen der beliebtesten Bibliotheken ausgestattet ist.

Ich habe mein Problem behoben, indem ich die preDexLibraries für alle Module deaktiviert habe:

dexOptions {
        preDexLibraries false
        ...

NoClassDefFoundError kann auch auftreten, wenn a statisch Der Initialisierer versucht, ein Ressourcenpaket zu laden, das zur Laufzeit nicht verfügbar ist, beispielsweise eine Eigenschaftendatei, aus der die betroffene Klasse zu laden versucht META-INF Verzeichnis, ist aber nicht dort.Wenn Sie es nicht fangen NoClassDefFoundError, manchmal können Sie nicht den vollständigen Stack-Trace sehen;Um dies zu überwinden, können Sie vorübergehend a verwenden catch Klausel für Throwable:

try {
    // Statement(s) that cause the affected class to be loaded
} catch (Throwable t) {
    Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}

Wenn jemand deswegen hierher kommt java.lang.NoClassDefFoundError: org/apache/log4j/Logger Fehler, in meinem Fall wurde es erstellt, weil ich log4j 2 verwendet habe (aber ich habe nicht alle mitgelieferten Dateien hinzugefügt) und einige Abhängigkeitsbibliotheken log4j 1 verwendet haben.Die Lösung bestand darin, die Log4j 1.x-Brücke hinzuzufügen:das Gefäss log4j-1.2-api-<version>.jar was mit log4j 2 geliefert wird.Weitere Infos im log4j 2 Migration.

Zwei verschiedene Checkout-Kopien desselben Projekts

In meinem Fall lag das Problem darin, dass Eclipse nicht zwischen zwei verschiedenen Kopien desselben Projekts unterscheiden konnte.Ich habe einen am Trunk gesperrt (SVN-Versionskontrolle) und der andere arbeitet jeweils in einem Zweig.Ich habe eine Änderung in der Arbeitskopie als JUnit-Testfall ausprobiert, zu der das Extrahieren einer privaten inneren Klasse in eine eigene öffentliche Klasse gehörte, und während sie funktionierte, öffne ich die andere Kopie des Projekts, um mir eine andere anzuschauen Teil des Codes, der geändert werden musste.Irgendwann ist das NoClassDefFoundError tauchte auf und beschwerte sich darüber, dass die private innere Klasse nicht da sei;Durch einen Doppelklick im Stack-Trace gelangte ich zur Quelldatei in der falschen Projektkopie.

Durch Schließen der Stammkopie des Projekts und erneutes Ausführen des Testfalls konnte das Problem behoben werden.

Dieser Fehler kann durch Nichtprüfung verursacht werden Java-Version Anforderungen.

In meinem Fall konnte ich diesen Fehler beim Erstellen eines hochkarätigen Open-Source-Projekts beheben, indem ich von Java 9 auf Java 8 umstieg SDKMAN!.

sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu

Führen Sie dann eine Neuinstallation durch, wie unten beschrieben.


Beim Benutzen Maven Als Ihr Build-Tool ist es manchmal hilfreich – und normalerweise erfreulich, eine zu tun sauber Build „installieren“. mit deaktiviertem Testen.

mvn clean install -DskipTests

Nun das alles Wenn die Software erstellt und installiert wurde, können Sie mit den Tests fortfahren.

mvn test

Ich habe NoClassDefFound-Fehler erhalten, als ich keine Klasse auf der Registerkarte „Reihenfolge und Export“ im Java Build Path meines Projekts exportiert habe.Stellen Sie sicher, dass Sie auf der Registerkarte „Bestellen und Exportieren“ alle Abhängigkeiten, die Sie dem Build-Pfad des Projekts hinzufügen, mit einem Häkchen versehen.Sehen Eclipse-Warnung:XXXXXXXXXXX.jar wird nicht exportiert oder veröffentlicht.Es können Laufzeit-ClassNotFoundExceptions auftreten.

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.Für diese habe ich die Bibliotheksreferenz in eine Projektreferenz geändert (Build-Pfad -> Build-Pfad konfigurieren).

Und das Problem war verschwunden.

Ich hatte das gleiche Problem und war viele Stunden lang auf Lager.

Ich habe die Lösung gefunden.In meinem Fall wurde aus diesem Grund die statische Methode definiert.Die JVM kann kein anderes Objekt dieser Klasse erstellen.

Zum Beispiel,

private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");

Ich habe diese Meldung erhalten, nachdem ich zwei Dateien aus der SRC-Bibliothek entfernt hatte, und als ich sie zurückbrachte, wurde mir weiterhin diese Fehlermeldung angezeigt.

Meine Lösung war:Starten Sie Eclipse neu.Seitdem habe ich diese Nachricht nicht mehr gesehen :-)

Stellen Sie sicher, dass dies mit dem übereinstimmt module:app Und module:lib:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top