java.lang.NoClassDefFoundError: Klasse XXX konnte nicht initialisiert werden


164
public class PropHolder {
  public static Properties prop;

  static {
    //code for loading properties from file
  }
}

// Referencing the class somewhere else:
Properties prop = PropHolder.prop;

class PropHolderist eine Klasse für mich. Die Klasse befindet sich in derselben JAR-Datei der Hauptklasse. Das sollte also nicht so sein, weil JAR im Klassenpfad fehlt.

Wenn ich in die JAR-Datei von schaue jar tf myjarfile, kann ich die dort PropHolder.classaufgelistete sehen.

Übrigens: Der Code läuft auf meinem lokalen Computer einwandfrei. Konnte aber nicht funktionieren, wenn ich es mit einem Skript auf einem Linux-Server bereitstelle. Ich denke, es ist nicht das Problem des Codes. Aber aus irgendeinem Grund. Der Bereitstellungsprozess ist sehr schwer zu verfolgen.

Was könnte das Problem sein?


Entspricht die entsprechende Verzeichnisstruktur in Ihrem JAR dem Klassenpaket?
John B

müssen eine Quelle sehen, viele Dinge können dies verursachen. Zum Beispiel eine '
Paket'

3
Eine Ursache ist eine Ausnahme während der Initialisierung - gibt es eine andere Fehlerausgabe?
Michael Brewer-Davis

Antworten:


209

Meine beste Wette ist, dass es hier ein Problem gibt:

static {
    //code for loading properties from file
}

Es scheint, dass eine nicht erfasste Ausnahme aufgetreten ist und bis zum tatsächlichen ClassLoader weitergegeben wurde, der versucht, die Klasse zu laden. Wir würden jedoch einen Stacktrace benötigen, um dies zu bestätigen.

Entweder das oder es ist beim Erstellen einer PropHolder.propstatischen Variablen aufgetreten .


Ich habe immer wieder das gleiche Problem gehabt. Ich bin sicher, dass es an dem staticProblem liegt. Was muss getan werden, um das Problem zu lösen?
Viper

1
Sie müssen identifizieren, welche Ausnahme vom staticBlock ausgelöst wird . Um es zu debuggen, setzen Sie ein try/catch(Exception e)um den gesamten Block und protokollieren Sie die Ausnahme. Sie müssen diese Ausnahme beheben. Normalerweise wird die Ausnahme protokolliert, ist jedoch möglicherweise schwer zu finden, da sie während des Klassenladevorgangs protokolliert wird, was sehr früh erfolgen kann
John Vint

Ja, ich habe den Code try catchblockiert und es stand Failed to initialize ClassA. Ich denke es ist das Problem von JVM. Ich habe mein System neu gestartet und dann hat alles gut funktioniert. Wie kann ich dieses Problem in Zukunft lösen, ohne mein System neu zu starten, und das Problem mit einer einfachen Lösung lösen?
Viper

Das Nichtinitialisieren von ClassA ist ein Nebeneffekt von etwas anderem. Sie sollten sich die ansehen, causefalls verfügbar. A NoClassDefFoundErrorist immer mit einem anderen Fehler verbunden. Sie müssen ihn in den Protokollen suchen oder versuchen, ihn angemessener zu protokollieren (z. B. die Protokollierung in eine neue Datei im Dateisystem erzwingen)
John Vint

Es wäre leichter nachvollziehbar, wenn Java einen Fehler auslösen würde. CouldNotInitializeStaticPartOfClassError oder so. Dann würden wir als Entwickler wissen, wo wir suchen müssen.
Maarten

125

Sie erhalten eine, java.lang.NoClassDefFoundErrorwas NICHT bedeutet, dass Ihre Klasse fehlt (in diesem Fall würden Sie eine bekommen java.lang.ClassNotFoundException). Der ClassLoader hat beim Lesen der Klassendefinition einen Fehler beim Lesen der Klasse festgestellt.

Legen Sie einen Versuch / Fang in Ihren statischen Initialisierer und sehen Sie sich die Ausnahme an. Wenn Sie dort einige Dateien lesen und diese sich von Ihrer lokalen Umgebung unterscheiden, ist dies höchstwahrscheinlich die Ursache des Problems (möglicherweise kann die Datei nicht gefunden werden, keine Berechtigungen usw.).


1
Eine Klarstellung ist, dass NoClassDefFoundError zwar keine ClassNotFoundException impliziert, aber dennoch eine mögliche Ursache für NoClassDefFoundError ist.
John Vint

1
buf wenn du eine ClassNotFoundException hättest, würde / könnte der ClassLoader niemals versuchen, die Klasse zu laden, oder?
Jeha

4
Eine Klasse kann eine andere Klasse laden, die nicht gefunden wurde. Die Ursache in diesem Fall ist immer noch eine ClassNotFoundException
John Vint

1
Ich hätte klarstellen sollen, ich meinte nur eine Ausnahme.
GetCause

1
Dieser war hier wirklich hilfreich, da ich ungefähr 20 Minuten damit verbracht habe, zu überprüfen, ob die JAR (zu der die gemeldete Klasse gehört) enthalten ist. Als ich merkte, dass ich in die falsche Richtung schaue, verstand ich leicht, dass wahrscheinlich eine Anmerkungsklasse fehlt und voila, die gemeldete, wurde als deklariert @Stateless, also fügte ich einfach die entsprechende Abhängigkeit hinzu und konnte fortfahren. Danke für den Tipp!
RAM237

33

NoClassDefFoundError gibt keinen großen Hinweis darauf, was im statischen Block schief gelaufen ist. Es wird empfohlen, immer einen solchen Block im statischen {...} Initialisierungscode zu haben:

static {
  try {

    ... your init code here

  } catch (Throwable t) {
    LOG.error("Failure during static initialization", t);
    throw t;
  }
}

Wie geht das in Kotlin?
Marlon

Vielen Dank für den Hinweis. In meinem Fall bekam ich NPE bei der Initialisierung der statischen Leitung.
Abhishek

3

Ich hatte die gleiche Ausnahme, so habe ich das Problem gelöst:

Voraussetzungen:

  1. Junit-Klasse (und Test), die eine weitere Klasse erweitert hat.

  2. ApplicationContext wurde mit spring initialisiert und initiiert das Projekt.

  3. Der Anwendungskontext wurde in der @ Before-Methode initialisiert

Lösung:

Initialisieren Sie den Anwendungskontext über die @ BeforeClass-Methode, da für die übergeordnete Klasse auch einige Klassen erforderlich sind, die aus dem Anwendungskontext heraus initialisiert wurden.

Hoffe das wird helfen.


2

Wie oben erwähnt, kann dies eine Reihe von Dingen sein. In meinem Fall hatte ich eine statisch initialisierte Variable, die auf einem fehlenden Eintrag in meiner Eigenschaftendatei beruhte. Der fehlende Eintrag zur Eigenschaftendatei wurde hinzugefügt und das Problem wurde behoben.


1

Vor einigen Tagen habe ich die gleiche Frage wie Ihre gestellt. Der gesamte Code läuft gut auf meinem lokalen Computer, stellt sich jedoch als Fehler heraus (noclassdeffound & initialize). Also poste ich meine Lösung, aber ich weiß nicht warum, ich mache nur eine Möglichkeit. Ich hoffe, jemand weiß, dass dies erklärt wird. @ John Vint Zuerst zeige ich Ihnen mein Problem. Mein Code hat sowohl eine statische Variable als auch einen statischen Block. Als ich dieses Problem zum ersten Mal traf, versuchte ich die Lösung von John Vint und versuchte, die Ausnahme abzufangen. Ich habe jedoch nichts gefangen. Also dachte ich, es liegt daran, dass die statische Variable (aber jetzt weiß ich, dass sie dasselbe sind) und immer noch nichts gefunden hat. Also versuche ich den Unterschied zwischen dem Linux-Computer und meinem Computer zu finden. Dann stellte ich fest, dass dieses Problem nur auftritt, wenn mehrere Threads in einem Prozess ausgeführt werden (der Linux-Computer verfügt übrigens über doppelte Kerne und doppelte Prozesse). Das heißt, wenn zwei Tasks (beide verwenden den Code mit statischen Blöcken oder Variablen) im selben Prozess ausgeführt werden, geht dies schief. Wenn sie jedoch in unterschiedlichen Prozessen ausgeführt werden, sind beide in Ordnung. In der Linux-Maschine benutze ich

mvn -U clean  test -Dtest=path 

Um eine Aufgabe auszuführen, und weil meine statische Variable darin besteht, einen Container zu starten (oder vielleicht einen neuen Klassenladeprogramm zu initialisieren), bleibt sie so lange bestehen, bis die JVM stoppt, und die JVM stoppt nur, wenn alle Aufgaben in einem Prozess gestoppt sind. Jede Aufgabe startet einen neuen Container (oder Klassenlader) und verwirrt das JVM. Infolgedessen tritt der Fehler auf. Also, wie kann man das lösen? Meine Lösung besteht darin, dem Befehl maven einen neuen Befehl hinzuzufügen und jede Aufgabe in denselben Container zu verschieben.

-Dxxx.version=xxxxx #sorry can't post more

Vielleicht haben Sie dieses Problem bereits gelöst, hoffen aber dennoch, dass es anderen hilft, die das gleiche Problem haben.


Wenn der Code auf dem Linux-Computer ausgeführt wird, folgen Sie dem obigen Fehler. Es gibt ein weiteres Problem: java.lang.ExceptionInInitializerError: nullDies bedeutet, dass die Klasse im Klassenladeprogramm nicht gefunden werden kann oder nicht weiß, welche geladen werden soll (denke ich). Hast du das getroffen?
MonkeyKing

1

Ich hatte die gleiche Ausnahme - aber nur während ich im Debug-Modus lief, löste ich das Problem auf diese Weise (nach 3 ganzen Tagen): In der build.gradle hatte ich: "multiDexEnabled true" im Abschnitt defaultConfig festgelegt.

        defaultConfig {
    applicationId "com.xxx.yyy"
    minSdkVersion 15
    targetSdkVersion 28
    versionCode 5123
    versionName "5123"
    // Enabling multidex support.
    multiDexEnabled true
}

aber anscheinend war das nicht genug. aber als ich mich änderte:

public class MyAppClass  extends Application 

zu:

public class MyAppClass  extends MultiDexApplication 

das löste es. hoffe, das wird jemandem helfen


0

Wenn Sie an einem Android-Projekt arbeiten, stellen Sie sicher, dass Sie keine statischen Methoden für Android-Klassen aufrufen. Ich verwende nur JUnit + Mockito. Vielleicht helfen Ihnen einige andere Frameworks dabei, das Problem insgesamt zu vermeiden. Ich bin mir nicht sicher.

Mein Problem bestand darin, Uri.parse(uriString)als Teil eines statischen Initialisierers einen Unit-Test durchzuführen. Die Uri-Klasse ist eine Android-API, weshalb der Unit-Test-Build sie nicht finden konnte. Ich habe diesen Wert nullstattdessen geändert und alles wurde wieder normal.


0

Ich hatte die gleichen Probleme: java.lang.NoClassDefFoundError: Klasse com.xxx.HttpUtils konnte nicht initialisiert werden

static {
    //code for loading properties from file
}

Es ist das Umgebungsproblem. Das bedeutet, dass die Eigenschaften in application.yml falsch oder leer sind!


0

Ich stoße auf das gleiche Problem. Ich habe ein Bean-Objekt in einem statischen Block wie folgt gestartet:

static {
    try{
        mqttConfiguration = SpringBootBeanUtils.<MqttConfiguration>getBean(MqttConfiguration.class);
    }catch (Throwable e){
        System.out.println(e);
    }
 }

Nur weil der Prozess, bei dem mein Bohnenobjekt ausgelöst wurde, eine NPE verursachte, bekomme ich Probleme damit. Ich denke, Sie sollten Ihren statischen Codeblock sorgfältig prüfen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.