it-swarm.com.de

NoSuchFieldError Java

Ich bekomme einen NoSuchFieldError in meinem Code. Jetzt ist Oracle nicht sehr klar, warum dieser Fehler nur mit der folgenden Fehlermeldung ausgelöst wird: Dieser Fehler kann nur zur Laufzeit auftreten, wenn die Definition einer Klasse inkompatibel geändert wurde.

Kann mir jemand erklären, wie man eine Klasse "unvereinbar ändern" kann? Die Klasse, über die ich spreche, erstreckt sich über eine ganze Reihe von Klassen, daher vermute ich, dass es damit zu tun hat, aber ich weiß nicht, wo ich anfangen soll oder was ich suche.

33
Tim

Dieser Fehler wird normalerweise ausgelöst, wenn Sie den Code nur teilweise neu kompilieren. Sie haben alten Code, der auf ein Feld verweist, das in den neu kompilierten Klassendateien nicht mehr vorhanden ist.

Die Lösung besteht darin, alle Klassendateien zu löschen und alles frisch zu kompilieren.

Update: Wenn Sie immer noch die gleiche Fehlermeldung erhalten, nachdem Sie alles neu kompiliert haben, kompilieren Sie wahrscheinlich mit einer Version einer externen Bibliothek und verwenden zur Laufzeit eine andere.

Jetzt müssen Sie zunächst die Klasse ermitteln, die das Problem verursacht (es sieht so aus, als hätten Sie dies bereits getan) und führen Sie dann Ihre Anwendung mit der Befehlszeilenoption -verbose:class aus. Es werden viele Klassenladeinformationen auf Ihrem Standard ausgegeben, und Sie können herausfinden, von wo die problematische Klasse genau geladen wird. 

53
biziclop

Als der Compiler den Code kompilierte, der den Fehler auslöst, gab es eine andere Klasse mit einem Feld, und Ihre Klasse konnte auf dieses Feld zugreifen (entweder den Wert lesen oder ändern).

Zur Laufzeit hat die andere Klasse irgendwie kein Feld mit diesem Namen, was zu dem genannten Fehler führt.

Ein Grund könnte sein, dass sich die zweite Klasse geändert hat, ohne dass die erste neu kompiliert wurde .. __ Rekompilieren Sie alle Ihre Klassen, und Sie sollten entweder einen Compiler-Fehler erhalten (der Ihnen mehr Informationen zur Lösung dieses Problems liefert) oder die Klasse Verweise auf die richtige Klasse.

Ein anderer Grund könnte sein, dass Sie eine Klasse in mehr als einer JAR-Datei (oder einem Verzeichnis) im Klassenpfad (in verschiedenen Versionen) haben, was dazu führt, dass eine andere Klasse die falsche verwendet. Überprüfen Sie alle Gläser in doppelten Klassen.

6
Paŭlo Ebermann

Wenn Sie diese Fehler in einer IDE (in meinem Fall Eclipse) nachverfolgen, sollten Sie auf die Abhängigkeiten von Projekten achten, von denen Ihr Projekt abhängt. Wenn Sie unterschiedliche Versionen einer Bibliothek in verschiedenen abhängigen Projekten verwenden, kann der Klassenpfadladeprogramm die falsche Version ermitteln. Dazu gehört, dass ein Projekt von einem Jar abhängig ist, das von einem Eclipse-Projekt erstellt wurde, und ein anderes Projekt, das von diesem Projekt und dem Projekt abhängig ist, aus dem der Jar generiert wurde. Die veralteten Klassen im jar könnten möglicherweise anstelle der Klassen aus dem Projekt geladen werden. 

Beispiel:

project1 hängt von project2 und project3 ab

project3 hängt von project2.jar ab, einer Jar, die aus den Klassendateien in project2 generiert wird.

Ein letztes statisches Feld wird einer Klasse in project2 hinzugefügt, die erneut kompiliert wird , Während project2.jar nicht neu erstellt wird

Das Ausführen von project1 kann zu einer Ausnahme führen, da die Klassen von project2 direkt aus dem Projekt geladen werden können OR der Jar, der das Feld nicht hat

4
Ryan O'Meara

Dies bedeutet, dass Sie wahrscheinlich eine Klasse neu kompiliert haben, auf die eine andere bereits kompilierte Klasse angewiesen war - und nicht die abhängige Klasse neu.

Zum Beispiel:

public class MyClass {
    public int num;
    public MyClass() { num = 1; }
}

public class MyDependingClass {
    private int foo;
    public MyDependingClass(MyClass init) {
        foo = init.num;
    }
}

Sie kompilieren die beiden Klassen also vermutlich von Hand neu (normalerweise würde ein IDE den Projektarbeitsbereich für Sie aktualisieren, damit Sie mit den entsprechenden Klassen umgehen können).

Und es hat funktioniert.

Später beschließen Sie, MyClass umzuwandeln:

public class MyClass {
    private int innernum;
    public int getNum() {
        return innernum;
    }
    public MyClass() { innernum = 1; }
}

Wenn Sie MyClass und not MyDependingClass kompilieren, wenn Sie Ihr Programm ausführen und eine Instanz von MyDependingClass erstellen, erhalten Sie Ihr NoSuchFieldError .

Die kurzfristige Korrektur besteht wahrscheinlich darin, alle Klassen in Ihrem Arbeitsbereich neu zu kompilieren, wodurch der Fehler angezeigt wird.

Die langfristige Lösung besteht darin, Eclipse oder NetBeans oder eine andere IDE zu verwenden, die dies für Sie erledigt.

3
Charles Goodwin

Obwohl die zugrunde liegende Ursache die gleiche ist, wie in den oberen Antworten beschrieben, war mein Problem etwas anders als die anderen Antworten, die ich hier gefunden habe, und ich dachte, ich würde sie teilen.

Ich arbeite an einem großen Projekt, bei dem mehrere Maven Poms über das gesamte Projekt verteilt sind. Ein Kollege hat die Versionsnummer einer der Abhängigkeiten aktualisiert, ohne jeden einzelnen Ort, an dem diese Abhängigkeit auftrat, zu aktualisieren, was zu nicht übereinstimmenden Bibliotheken im Klassenpfad führte.

Die Lösung bestand darin, jedes Auftreten dieser Abhängigkeit auf dieselbe Versionsnummer zu aktualisieren. Um dies zu verhindern, haben wir dort eine Variable hinzugefügt und steuern nun die Versionsnummer dieser Abhängigkeiten von einer Stelle aus.

0
Old Schooled

Es war ziemlich schwierig für mich, also schreibe ich meine Lösung. 

Ich habe in IntelliJ mit Boot gearbeitet, alles war in Ordnung, alle Java 8-Versionen waren entsprechend eingerichtet. 

Nach einigen Stunden habe ich irgendwie die javac -version auf dem Terminal überprüft und weißt du, was auf Version 9 eingestellt war. Also achte auf die Suche nach javac Profil, auf IntelliJ usw. sollte ich mich nicht darum kümmern müssen. 

Ich hoffe es hilft!

0
Kejsi Struga

Verstehe diesen Fehler:

Dies ist ein Java.lang.LinkageError-Fehler, der auftritt, wenn jvm die verknüpften Klassen zu verknüpfen versucht. Beachten Sie, dass der Code zuerst kompiliert wird (mit den abhängigen Klassen), dann werden alle beteiligten Klassen geladen und dann diese Klassen miteinander verknüpft. 

Denken Sie an den Fehler: NoSuchField, wenn Sie die Zielklasse verknüpfen, ist das Feld nicht vorhanden. Beim Kompilieren sollte die Klasse jedoch dieses Feld haben, andernfalls kann der Code nicht kompiliert werden. Bei der Verknüpfung stellt der jvm fest, dass dieses Feld nicht vorhanden ist. Der einzige Grund ist, dass wir mit einer Klasse mit diesem Feld kompilieren und eine andere Version dieser Klasse (die dieses Feld nicht hat) geladen und verlinkt wird. 

Entscheide deine Situation zwischen zwei häufigen Gründen für diesen Fehler

Normalerweise ist die falsch geladene Klasse entweder ein von Ihnen geänderter Quellcode oder eine Klasse in einem Ihrer abhängigen JAR-Pakete. Wir können dies entscheiden, indem wir die falsch geladene Klasse suchen, indem Sie dem jvm, das versucht, Ihre Anwendung in Ihrem IDE auszuführen, das Argument -verbose:class hinzufügen. Dieses Argument gibt alle geladenen Klassen in der Konsole aus. In Eclipse platzieren wir es in: Klicken Sie mit der rechten Maustaste auf Ihr Projekt -> Ausführen als -> Ausführen von Konfigurationen -> im Feld arguments -> VM arguement.

Nachdem Sie die falsch geladene Klasse gefunden haben, ist es normalerweise eine Klasse, die Sie über den Quellcode in Ihrem Projekt verfügen, oder es befindet sich in einem JAR-Paket, von dem Ihr Projekt abhängig ist.

Lösung für den Quellcode:

Die Chancen stehen gut, dass Sie diese Klasse geändert haben (das Feld im Quellcode hinzugefügt), aber nicht neu kompiliert wurde. Es kann verschiedene Ursachen haben, aber Sie sollten die .class-Datei der alten Version dieser Klasse löschen und erneut kompilieren, damit die neue Version .class-Datei dieses Feld enthält.

Lösung für das jar-Paket:

Sie sollten versuchen, das Projekt das korrekte JAR-Paket laden zu lassen. Aber warum eine andere Version entwickelt wird, liegt in der Regel daran, dass beide davon abhängig sind (von verschiedenen Teilen Ihres Projekts). Die Situation ist sehr einfach (und existiert im realen Projekt möglicherweise nicht). Wenn Sie Codes schreiben, die direkt von beiden abhängen, wählen Sie einfach einen aus und lassen Sie einen anderen fallen.

Aber die Chancen sind, dass Ihr Code indirekt von ihnen abhängt. Und Sie möchten Ihren Code nicht ändern (oder so wenig wie möglich ändern). 

Eine Lösung ist, dass Sie Ihre eigene ClassLoader schreiben, um beide zu analysieren: Können Sie zwei Java-Klassen mit demselben Namen und demselben Paket verwenden? (Ich habe es nicht probiert)

Wenn Sie sich entscheiden, die richtige Version (die solche field enthält) zu laden, und Ihren Code, der indirekt von der wrong-Version abhängig ist (hoffnungsvoll), funktioniert, haben wir eine sehr einfache Lösung: Lassen Sie Ihr Projekt die richtige Version auswählen.

Nehmen Sie zum Beispiel Eclipse. Sie können das Order and Export-Tag in Ihrer Java Build Path-Eigenschaft verwenden. Passen Sie einfach die Reihenfolge an, um die korrekte Version vor der wrong-Version zu lassen, da die Funktion von Order:

Einerseits fungiert es als Reihenfolge der Auflösung für Ressourcen verwendet im Gebäude des betreffenden Projekts (der Teil "Bestellung").

Wenn die richtige Version oder die falsche Version dort nicht angezeigt wird, sollten Sie aufgrund der Funktion von Export part feststellen, welches Paket davon abhängig ist, und deren Reihenfolge anpassen. Lesen Die Registerkarte "Bestellen und Exportieren" in "Java Build Path" für Details.

0
ZhaoGang