Wie behebe ich einen NoSuchMethodError?

175

NoSuchMethodErrorBeim Ausführen meines Java-Programms wird eine Fehlermeldung angezeigt. Was ist los und wie behebe ich das?

John Meagher
quelle
11
In Netbeans: Klicken Sie mit der rechten Maustaste auf das Projekt auf der Registerkarte Projekte und verwenden Sie "Bereinigen und Erstellen". Hat es für mich gelöst.
Heinzlmaen
3
Auch in Intellij Idea löst die Neuerstellung manchmal das Problem
Hawk
Dieser Artikel ist sehr hilfreich für dieses Problem Reflectoring.io/nosuchmethod
Michael Smith

Antworten:

225

Ohne weitere Informationen ist es schwierig, das Problem genau zu bestimmen. Die Hauptursache ist jedoch, dass Sie höchstwahrscheinlich eine Klasse für eine andere Version der Klasse kompiliert haben, bei der eine Methode fehlt, als die, die Sie beim Ausführen verwenden.

Sehen Sie sich den Stack-Trace an ... Wenn die Ausnahme beim Aufrufen einer Methode für ein Objekt in einer Bibliothek auftritt, verwenden Sie beim Kompilieren und Ausführen höchstwahrscheinlich separate Versionen der Bibliothek. Stellen Sie sicher, dass Sie an beiden Stellen die richtige Version haben.

Wenn die Ausnahme beim Aufrufen einer Methode für Objekte auftritt, die von von Ihnen erstellten Klassen instanziiert wurden , scheint Ihr Erstellungsprozess fehlerhaft zu sein. Stellen Sie sicher, dass die Klassendateien, die Sie tatsächlich ausführen, beim Kompilieren aktualisiert werden.

Vetle
quelle
3
Wir haben kürzlich die Ursache für eine dieser Ursachen entdeckt und es stellte sich heraus, dass beim Erstellungsprozess Klassendateien eingerichtet wurden, bevor der Java-Server heruntergefahren wurde. Wir haben dies getroffen, weil der Java-Server einige Klassen nicht geladen hatte und dann geladen wurde einige, aber es bekam diese neuen, und da der neue Code auf Methoden verwies, die die alten Klassen nicht hatten ... Bingo, NoSuchMethodError
vazor
108

Ich hatte Ihr Problem und so habe ich es behoben. Mit den folgenden Schritten können Sie eine Bibliothek hinzufügen. Ich hatte die ersten beiden Schritte richtig gemacht, aber den letzten nicht, indem ich die Datei ".jar" direkt aus dem Dateisystem in den Ordner "lib" in meinem Eclipse-Projekt gezogen hatte. Außerdem musste ich die vorherige Version der Bibliothek sowohl aus dem Erstellungspfad als auch aus dem Ordner "lib" entfernen.

Schritt 1 - Fügen Sie .jar hinzu, um den Pfad zu erstellen

Geben Sie hier die Bildbeschreibung ein

Schritt 2 - Quellen und Javadocs zuordnen (optional)

Geben Sie hier die Bildbeschreibung ein

Schritt 3 - Ziehen Sie die JAR-Datei tatsächlich in den Ordner "lib" (nicht optional).

Geben Sie hier die Bildbeschreibung ein

Chris Dutrow
quelle
75
+1 für "Jeder erwartet von Ihnen, dass Sie wissen, wie man es benutzt, und wenn Sie es nicht tun, stimmen sie Ihre Frage ab."
Vikram
73

Beachten Sie, dass Sie im Fall von Reflexion einen erhalten NoSuchMethodException, während Sie bei nicht reflektierendem Code einen erhalten NoSuchMethodError. Ich neige dazu, an sehr unterschiedlichen Orten zu suchen, wenn ich mit einem gegen den anderen konfrontiert werde.

erickson
quelle
Mit anderen Worten, Sie sagen, dass Sie eine NoSuchMethodException erhalten, wenn Sie Reflection verwenden, um eine Methode für eine Klasse abzurufen, und die Methode nicht gefunden wird. Wenn Sie sich jedoch in einem Szenario befinden, in dem Sie Ihren Code für einige Bibliotheken kompiliert haben und auf dem Server andere Bibliotheken (möglicherweise neuere, möglicherweise ältere) vorhanden sind, erhalten Sie den NoSuchMethodError. Korrigiere mich, wenn ich falsch liege.
Victor
50

Wenn Sie Zugriff auf die Änderung der JVM-Parameter haben, sollten Sie durch Hinzufügen einer ausführlichen Ausgabe sehen können, welche Klassen aus welchen JAR-Dateien geladen werden.

java -verbose:class <other args>

Wenn Ihr Programm ausgeführt wird, sollte die JVM Dump-to-Standard-Out-Informationen wie:

...

[Junit.framework.Assert aus Datei geladen: / C: /Program%20Files/junit3.8.2/junit.jar]

...

matt b
quelle
3
+1 Genial! Ich habe ein böses kleines Problem mit dieser Methode gelöst, danke. Dies ist eine hervorragende Möglichkeit, um herauszufinden, wann sich Klassen irgendwie auf einen Klassenpfad geschlichen haben.
Duncan Jones
1
+1 Du hast meinen Tag gerettet! Es war nur eine Bibliothek, deren Quellen alte Klassen mit demselben Namen enthielten.
Andrii Nemchenko
12

Dies wird normalerweise verursacht, wenn ein Build-System wie verwendet wird Apache Ant verwendet wird , das Java-Dateien nur kompiliert, wenn die Java-Datei neuer als die Klassendatei ist. Wenn Änderungen an einer Methodensignatur und Klassen die alte Version verwenden, werden die Dinge möglicherweise nicht korrekt kompiliert. Die übliche Lösung besteht darin, einen vollständigen Neuaufbau durchzuführen (normalerweise "Ameisen sauber", dann "Ameise").

Manchmal kann dies auch beim Kompilieren mit einer Version einer Bibliothek, aber mit einer anderen Version verursacht werden.

John Meagher
quelle
1
Tatsächlich scheint dies eher ein Problem zu sein, das für Java-Programmierer auftritt, die ein beliebiges Java-Entwicklungsframework verwenden: Maven, NetBeans und Apache Ant, wie Sie aus allen Antworten hier ersehen können.
HoldOffHunger
8

Wenn Sie Maven oder ein anderes Framework verwenden und dieser Fehler fast zufällig auftritt, versuchen Sie eine Neuinstallation wie ...

clean install

Dies funktioniert besonders wahrscheinlich, wenn Sie das Objekt geschrieben haben und wissen, dass es die Methode hat. Hat für mich gearbeitet.

HoldOffHunger
quelle
Dies gilt auch für Gradle-Builds.
Jonathan Landrum
4

Dies kann auch das Ergebnis der Verwendung von Reflexion sein. Wenn Sie Code haben, der eine Klasse reflektiert und eine Methode nach Namen extrahiert (z. B. mit Class.getDeclaredMethod("someMethodName", .....)), müssen Sie jedes Mal, wenn sich dieser Methodenname ändert, z. B. während eines Refactors, daran denken, die Parameter der Reflektionsmethode entsprechend zu aktualisieren neue Methodensignatur, oder der getDeclaredMethodAufruf löst a ausNoSuchMethodException .

Wenn dies der Grund ist, sollte der Stack-Trace den Punkt anzeigen, an dem die Reflektionsmethode aufgerufen wird, und Sie müssen nur die Parameter aktualisieren, um sie an die tatsächliche Methodensignatur anzupassen.

Nach meiner Erfahrung tritt dies gelegentlich auf, wenn private Methoden / Felder getestet werden und eine TestUtilitiesKlasse zum Extrahieren von Feldern für die Testüberprüfung verwendet wird. (Im Allgemeinen mit Legacy-Code, der nicht für Unit-Tests entwickelt wurde.)

rcreswick
quelle
3

Wenn Sie eine Webanwendung schreiben, stellen Sie sicher, dass sich im globalen Bibliotheksverzeichnis Ihres Containers und auch in Ihrer App keine widersprüchlichen Versionen einer JAR befinden. Möglicherweise wissen Sie nicht unbedingt, welches Glas vom Klassenladeprogramm verwendet wird.

z.B

  • tomcat / common / lib
  • mywebapp / WEB-INF / lib
Cheekysoft
quelle
2

Diese Probleme werden durch die Verwendung desselben Objekts in denselben zwei Klassen verursacht. Verwendete Objekte enthalten keine neue Methode, die die neue Objektklasse enthält.

Ex:

filenotnull=/DayMoreConfig.conf
16-07-2015 05:02:10:ussdgw-1: Open TCP/IP connection to SMSC: 10.149.96.66 at 2775
16-07-2015 05:02:10:ussdgw-1: Bind request: (bindreq: (pdu: 0 9 0 [1]) 900 900 GEN 52 (addrrang: 0 0 2000) ) 
Exception in thread "main" java.lang.NoSuchMethodError: gateway.smpp.PDUEventListener.<init>(Lgateway/smpp/USSDClient;)V
        at gateway.smpp.USSDClient.bind(USSDClient.java:139)
        at gateway.USSDGW.initSmppConnection(USSDGW.java:274)
        at gateway.USSDGW.<init>(USSDGW.java:184)
        at com.vinaphone.app.ttn.USSDDayMore.main(USSDDayMore.java:40)

-bash-3.00$ 

Diese Probleme werden durch die begleitende ähnliche Klasse 02 verursacht (1 in src, 1 in der JAR-Datei hier ist gateway.jar).

Quảng Trường Thời Đại
quelle
2

Dies bedeutet, dass die entsprechende Methode in der Klasse nicht vorhanden ist:

  1. Wenn Sie jar verwenden, dekompilieren Sie und überprüfen Sie, ob die jeweilige Version von jar die richtige Klasse hat.
  2. Überprüfen Sie, ob Sie die richtige Klasse aus Ihrer Quelle kompiliert haben.
Shrikant
quelle
2

Für mich ist es passiert, weil ich den Argumenttyp in der Funktion von Objekt a in String a geändert habe. Ich könnte es mit sauber lösen und wieder aufbauen

Tito
quelle
2

Ich habe diesen Fehler gerade behoben, indem ich meine Eclipse neu gestartet und die Anwendung ausgeführt habe. Der Grund für meinen Fall kann sein, dass ich meine Quelldateien ersetze, ohne mein Projekt oder Eclipse zu schließen. Was zu unterschiedlichen Versionen der von mir verwendeten Klassen führte.

Ryan Luo Xu
quelle
2

Versuchen Sie Folgendes: Entfernen Sie alle .class-Dateien in Ihren Projektverzeichnissen (und natürlich alle Unterverzeichnisse). Wiederaufbauen.

Manchmal mvn clean(wenn Sie maven verwenden) werden .class-Dateien, die manuell von erstellt wurden, nicht bereinigt javac. Und diese alten Dateien enthalten alte Signaturen, die dazu führen NoSuchMethodError.

WHOIF
quelle
2

Einfach zu vorhandenen Antworten hinzufügen. Ich hatte dieses Problem mit Tomcat in Eclipse. Ich hatte eine Klasse gewechselt und folgende Schritte ausgeführt:

  1. Reinigte und baute das Projekt in Eclpise

  2. mvn sauber installieren

  3. Tomcat neu gestartet

Trotzdem hatte ich den gleichen Fehler. Dann habe ich Tomcat gereinigt, das Tomcat-Arbeitsverzeichnis bereinigt und den Server neu gestartet, und mein Problem ist behoben. Hoffe das hilft jemandem

Code_Mode
quelle
1

Um die ursprüngliche Frage zu beantworten. Laut Java Docs hier :

"NoSuchMethodError" Wird ausgelöst, wenn eine Anwendung versucht, eine angegebene Methode einer Klasse (entweder statisch oder instanziell) aufzurufen, und diese Klasse keine Definition dieser Methode mehr hat.

Normalerweise wird dieser Fehler vom Compiler abgefangen. Dieser Fehler kann nur zur Laufzeit auftreten, wenn sich die Definition einer Klasse nicht kompatibel geändert hat.

  1. Wenn dies zur Laufzeit geschieht, überprüfen Sie, ob sich die Klasse mit der Methode im Klassenpfad befindet.
  2. Überprüfen Sie, ob Sie eine neue Version von JAR hinzugefügt haben und die Methode kompatibel ist.
Ziele erreichen
quelle
1

Ich habe dieses Problem in Eclipse behoben, indem ich eine Junit-Testdatei umbenannt habe.
In meinem Eclipse-Arbeitsbereich habe ich ein App-Projekt und ein Testprojekt.
Das Testprojekt hat das App-Projekt als erforderliches Projekt im Erstellungspfad.

Es wurde der NoSuchMethodError abgerufen.
Dann wurde mir klar, dass die Klasse im Testprojekt denselben Namen hatte wie die Klasse im App-Projekt.

App/  
  src/
     com.example/  
       Projection.java
Test/  
  src/
     com.example/
       Projection.java

Nach dem Umbenennen des Tests in den korrekten Namen "ProjectionTest.java" wurde die Ausnahme behoben.

Dave Inlow
quelle
Ich hatte ein ähnliches Problem. Ich hatte eine Abhängigkeitsklasse mit demselben vollständigen kanonischen Namen. Nach dem Umbenennen verschwand die Ausnahme.
MoralejaSinCuentoNiProverbio
1

Ich hatte den gleichen Fehler:

  Exception in thread "main" java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonGenerator.writeStartObject(Ljava/lang/Object;)V
        at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:151)
        at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
        at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3681)
        at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3057)

Um dies zu lösen, überprüfte ich zunächst das Modulabhängigkeitsdiagramm ( click in your POM the combination -> Ctrl+Alt+Shift+Uoder right click in your POM -> Maven -> Show dependencies), um zu verstehen, wo genau der Konflikt zwischen Bibliotheken war (Intelij IDEA). In meinem speziellen Fall hatte ich verschiedene Versionen von Jackson-Abhängigkeiten.

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

1) Also habe ich direkt in meinem POM des Projekts explizit die höchste Version hinzugefügt - 2.8.7 dieser beiden.

In Eigenschaften:

<jackson.version>2.8.7</jackson.version>

Und als Abhängigkeit:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>

2) Es kann aber auch mit Abhängigkeitsausschlüssen gelöst werden .

Nach dem gleichen Prinzip wie im folgenden Beispiel:

  <dependency>
      <groupId>group-a</groupId>
      <artifactId>artifact-a</artifactId>
      <version>1.0</version>
          <exclusions>
             <exclusion>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
             </exclusion>
         </exclusions>
  </dependency>

Abhängigkeiten mit unerwünschten Versionen werden von Ihrem Projekt ausgeschlossen.

invzbl3
quelle
1

In meinem Fall hatte ich ein Multi-Modul-Projekt und das Szenario war wie com.xyz.TestClassim Modul Aund sowie im Modul Bund Modul Awar vom Modul abhängig B. Beim Erstellen eines Assembly-JARs wurde meiner Meinung nach nur eine Version der Klasse beibehalten, wenn diese nicht über die aufgerufene Methode verfügt. Dann wurde eine NoSuchMethodErrorLaufzeitausnahme angezeigt, aber die Kompilierung war in Ordnung.

Siehe auch: https://reflectoring.io/nosuchmethod/

Gaurav Khare
quelle
0

Ich hatte ein ähnliches Problem, als ich Methodensignaturen in meiner Anwendung änderte. Durch Bereinigen und Wiederherstellen meines Projekts wurde der "NoSuchMethodError" behoben.

Knorman
quelle
0

Die obige Antwort erklärt sich sehr gut. Nur um eines hinzuzufügen. Wenn Sie Eclipse verwenden, verwenden Sie Strg + Umschalt + T und geben Sie die Paketstruktur der Klasse ein (z. B. gateway.smpp.PDUEventListener). Dort finden Sie alle Jars / Projekte, in denen sie vorhanden sind . Entfernen Sie unnötige Gläser aus dem Klassenpfad oder fügen Sie sie oben im Klassenpfad hinzu. Jetzt wird es richtig aufnehmen.

Prinz
quelle
0

Ich bin auf ein ähnliches Problem gestoßen.

Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I

Schließlich stellte ich fest, dass die Hauptursache darin bestand, den Datentyp der Variablen zu ändern.

  1. Employee.java-> Enthält die Variable ( EmpId), deren Datentyp von intnach geändert wurde String.
  2. ReportGeneration.java-> Ruft den Wert mit dem Getter ab getEmpId().

Wir sollen das Glas neu bündeln, indem wir nur die modifizierten Klassen einbeziehen. Da es keine Änderung gab, habe ReportGeneration.javaich nur die Employee.classIn-Jar-Datei aufgenommen. Ich musste die ReportGeneration.classDatei in das Glas aufnehmen, um das Problem zu lösen.

AnonymousCoder
quelle
0

Ich hatte das gleiche Problem. Dies wird auch verursacht, wenn in Klassen Mehrdeutigkeiten bestehen. Mein Programm hat versucht, eine Methode aufzurufen, die in zwei JAR-Dateien vorhanden ist, die sich am selben Speicherort / Klassenpfad befinden. Löschen Sie eine JAR-Datei oder führen Sie Ihren Code so aus, dass nur eine JAR-Datei verwendet wird. Stellen Sie sicher, dass Sie nicht dieselbe JAR oder verschiedene Versionen derselben JAR verwenden, die dieselbe Klasse enthalten.

DISP_E_EXCEPTION [Schritt] [] [Z-JAVA-105 Java-Ausnahme java.lang.NoSuchMethodError (com.example.yourmethod)]

ShankarDaruga
quelle
0

Meistens wird java.lang.NoSuchMethodError vom Compiler abgefangen, aber manchmal kann es zur Laufzeit auftreten. Wenn dieser Fehler zur Laufzeit auftritt, kann der einzige Grund die Änderung der Klassenstruktur sein, die ihn inkompatibel gemacht hat.

Beste Erklärung: https://www.journaldev.com/14538/java-lang-nosuchmethoderror

Yash P Shah
quelle
0

Ich habe auch diesen Fehler festgestellt.

Mein Problem war, dass ich die Signatur einer Methode geändert habe, so etwas wie

void invest(Currency money){...}

in

void invest(Euro money){...}

Diese Methode wurde aus einem ähnlichen Kontext wie aufgerufen

public static void main(String args[]) {
    Bank myBank = new Bank();

    Euro capital = new Euro();
    myBank.invest(capital);
}

Der Compiler schwieg in Bezug auf Warnungen / Fehler, da das Kapital sowohl Währung als auch Euro ist.

Das Problem trat aufgrund der Tatsache auf, dass ich nur die Klasse kompiliert habe, in der die Methode definiert wurde - Bank, aber nicht die Klasse, von der aus die Methode aufgerufen wird, die die main () -Methode enthält.

Dieses Problem tritt möglicherweise nicht zu häufig auf, da das Projekt am häufigsten manuell neu erstellt oder eine Build-Aktion automatisch ausgelöst wird, anstatt nur die eine geänderte Klasse zu kompilieren.

Mein Anwendungsfall war, dass ich eine JAR-Datei generiert habe, die als Hotfix verwendet werden sollte und die App.class nicht enthielt, da diese nicht geändert wurde. Es machte für mich Sinn, es nicht aufzunehmen, da ich die Basisklasse des ursprünglichen Arguments durch Vererbung beibehalten habe.

Die Sache ist, wenn Sie eine Klasse kompilieren, ist der resultierende Bytecode irgendwie statisch , mit anderen Worten, es ist eine harte Referenz .

Der ursprüngliche zerlegte Bytecode (generiert mit dem Javap-Tool) sieht folgendermaßen aus:

 #7 = Methodref          #2.#22         // Bank.invest:(LCurrency;)V

Nachdem der ClassLoader die neue kompilierte Bank.class geladen hat, findet er eine solche Methode nicht. Es sieht so aus, als ob sie entfernt und nicht geändert wurde, daher der genannte Fehler.

Hoffe das hilft.

Mihai Savin
quelle
0

In meinem Fall bestand das Problem darin, dass zwei Versionen derselben Bibliothek im Erstellungspfad vorhanden waren. Die ältere Version der Bibliothek hatte diese Funktion nicht und die neuere.

KK
quelle
0

Ich hatte ein ähnliches Problem mit meinem Gradle-Projekt mit Intelij. Ich habe es gelöst, indem ich das .gradle-Paket gelöscht habe (siehe Abbildung unten) und das Projekt neu erstellt habe. .gradle-Paket

J. Orlando
quelle
0

NoSuchMethodError: Ich habe ein paar Stunden damit verbracht, dieses Problem zu beheben. Schließlich wurde es behoben, indem ich nur den Paketnamen umbenannte, bereinigte und erstellte ... Versuchen Sie zuerst, die Erstellung zu bereinigen, wenn dies nicht funktioniert. Versuchen Sie, den Klassennamen oder den Paketnamen und den sauberen Build umzubenennen. .es sollte behoben werden. Viel Glück.

Shirish Singh
quelle
-2

Wenn sich Ihr Dateiname von dem Klassennamen unterscheidet, der die Hauptmethode enthält, besteht die Möglichkeit, dass dieser Fehler verursacht wird.

Amit Walke
quelle