Come riparo un NoSuchMethodError?


178

Ricevo un NoSuchMethodErrorerrore durante l'esecuzione del mio programma Java. Cosa c'è che non va e come posso ripararlo?


11
In Netbeans: fai clic con il pulsante destro del mouse sul progetto nella scheda Progetti, usa "Pulisci e costruisci". Risolto per me.
Heinzlmaen,

3
Anche in Intellij Idea, la ricostruzione a volte risolve il problema
Hawk,

1
Questo articolo è molto utile per questo problema reflectoring.io/nosuchmethod
Michael Smith,

Risposte:


228

Senza ulteriori informazioni è difficile individuare il problema, ma la causa principale è che molto probabilmente hai compilato una classe rispetto a una versione diversa della classe in cui manca un metodo, rispetto a quella che stai utilizzando durante l'esecuzione.

Guarda la traccia dello stack ... Se l'eccezione appare quando si chiama un metodo su un oggetto in una libreria, molto probabilmente stai usando versioni separate della libreria durante la compilazione e l'esecuzione. Assicurati di avere la versione giusta in entrambi i posti.

Se l'eccezione appare quando si chiama un metodo su oggetti istanziati dalle classi si apportate, allora il vostro processo di generazione sembra essere difettoso. Assicurarsi che i file di classe in esecuzione siano aggiornati durante la compilazione.


3
Recentemente abbiamo scoperto la causa di uno di questi e si è scoperto che il processo di compilazione stava mettendo in atto i file di classe prima che il server java fosse spento, e l'abbiamo colpito perché il server java non aveva caricato alcune classi e quindi si è caricato alcuni ma ne ottennero di nuovi, e poiché il nuovo codice si riferiva a metodi che le vecchie classi non avevano ... bingo,
NoSuchMethodError

"Guarda la traccia dello stack ..." - Beh, vado quasi sempre a controllare l'ultima Caused bysezione della traccia dello stack per trovare la classe / vaso colpevole
KrishPrabakar

108

Stavo avendo il tuo problema, ed è così che l'ho risolto. I seguenti passaggi sono un modo di lavorare per aggiungere una libreria. Avevo fatto i primi due passi giusti, ma non avevo fatto l'ultimo trascinando il file ".jar" direttamente dal file system nella cartella "lib" sul mio progetto eclipse. Inoltre, ho dovuto rimuovere la versione precedente della libreria sia dal percorso di compilazione che dalla cartella "lib".

Passaggio 1: aggiungi .jar per creare il percorso

inserisci qui la descrizione dell'immagine

Passaggio 2: Associa fonti e javadocs (facoltativo)

inserisci qui la descrizione dell'immagine

Passaggio 3: trascinare effettivamente il file .jar nella cartella "lib" (non facoltativo)

inserisci qui la descrizione dell'immagine


75
+1 per "Tutti si aspettano che tu sappia come usarlo e, in caso contrario, declassano la tua domanda."
Vikram,

73

Si noti che in caso di riflessione, si ottiene un NoSuchMethodException, mentre con un codice non riflettente, si ottiene NoSuchMethodError. Tendo ad andare a cercare in posti molto diversi di fronte l'uno rispetto all'altro.


In altre parole, stai dicendo che se stai usando la reflection per ottenere un metodo su una classe e il metodo non viene trovato, otterrai una NoSuchMethodException. Ma se ti trovi in ​​uno scenario in cui hai compilato il tuo codice su alcune librerie e sul server hai altre librerie (forse più recenti, forse più vecchie), ottieni NoSuchMethodError. Correggimi se sbaglio.
Victor,

È corretto, @Victor
KrishPrabakar

51

Se si ha accesso per modificare i parametri JVM, l'aggiunta di un output dettagliato dovrebbe consentire di vedere quali classi vengono caricate da quali file JAR.

java -verbose:class <other args>

Quando viene eseguito il programma, JVM dovrebbe scaricare informazioni standard come:

...

[Caricato junit.framework.Assert dal file: / C: /Program%20Files/junit3.8.2/junit.jar]

...


3
+1 brillante! Ho risolto un brutto piccolo problema usando questo metodo, grazie. Questo è un modo eccellente per scoprire quando le classi si sono insinuate in qualche modo su un sentiero di classe.
Duncan Jones,

1
+1 Mi hai salvato la giornata! Era solo una biblioteca che includeva vecchie classi con gli stessi nomi nelle sue fonti.
Andrii Nemchenko,

12

Questo di solito è causato quando si utilizza un sistema di generazione come Apache Ant che compila i file java solo quando il file java è più recente del file di classe. Se una firma del metodo cambia e le classi utilizzano la versione precedente, le cose potrebbero non essere compilate correttamente. La solita correzione è fare una ricostruzione completa (di solito "formica pulita" e poi "formica").

A volte ciò può essere causato anche durante la compilazione su una versione di una libreria ma in esecuzione su una versione diversa.


1
In realtà, questo sembra più un problema che si presenta per i programmatori Java che stanno utilizzando qualsiasi framework di sviluppo Java: Maven, NetBeans e Apache Ant, come puoi vedere da tutte le risposte qui.
HoldOffHunger

8

Se si utilizza Maven o un altro framework e si ottiene questo errore in modo quasi casuale, provare un'installazione pulita come ...

clean install

Questo è particolarmente probabile che funzioni se hai scritto l'oggetto e sai che ha il metodo. Ha funzionato per me.


Questo è anche il caso delle build Gradle.
Jonathan Landrum,

4

Questo può anche essere il risultato dell'uso della riflessione. Se si dispone di codice che si riflette su una classe ed estrae un metodo per nome (ad es .: con Class.getDeclaredMethod("someMethodName", .....)), ogni volta che cambia il nome del metodo, ad esempio durante un refattore, sarà necessario ricordare di aggiornare i parametri al metodo di riflessione in modo che corrispondano al firma del nuovo metodo, altrimenti la getDeclaredMethodchiamata genererà a NoSuchMethodException.

Se questo è il motivo, la traccia dello stack dovrebbe mostrare il punto in cui viene invocato il metodo reflection e sarà sufficiente aggiornare i parametri in modo che corrispondano alla firma del metodo effettivo.

Nella mia esperienza, ciò si presenta occasionalmente quando si testano unità metodi / campi privati ​​e si usa una TestUtilitiesclasse per estrarre campi per la verifica del test. (Generalmente con un codice legacy che non è stato progettato tenendo conto dei test unitari.)


3

Se stai scrivendo una webapp, assicurati di non avere versioni in conflitto di un vaso nella directory della libreria globale del tuo contenitore e anche nella tua app. Potresti non sapere necessariamente quale jar viene utilizzato dal classloader.

per esempio

  • Tomcat / common / lib
  • mywebapp / WEB-INF / lib

2

Questi problemi sono causati dall'uso dello stesso oggetto nelle stesse due classi. Gli oggetti utilizzati non contengono un nuovo metodo è stato aggiunto che contiene la nuova classe di oggetti.

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$ 

Questi problemi sono causati dalla concomitante classe 02 simile (1 in src, 1 nel file jar qui è gateway.jar)


2

Significa che il rispettivo metodo non è presente nella classe:

  1. Se stai usando jar, decompila e controlla se la rispettiva versione di jar ha una classe corretta.
  2. Controlla se hai compilato la classe corretta dalla tua fonte.

2

Per me è successo perché ho cambiato il tipo di argomento nella funzione, dall'oggetto a, alla stringa a. Potrei risolverlo con clean e build di nuovo


2

Ho appena risolto questo errore riavviando Eclipse ed eseguendo l'applicazione. Il motivo del mio caso potrebbe essere perché sostituisco i miei file di origine senza chiudere il mio progetto o Eclipse. Che ha causato diverse versioni delle classi che stavo usando.


2

Prova in questo modo: rimuovi tutti i file .class nelle directory del tuo progetto (e, ovviamente, in tutte le sottodirectory). Ricostruire.

A volte mvn clean(se stai usando Maven) non pulisce i file .class creati manualmente da javac. E quei vecchi file contengono vecchie firme, che portano a NoSuchMethodError.


2

Aggiungo solo alle risposte esistenti. Stavo affrontando questo problema con Tomcat in Eclipse. Avevo cambiato una classe e ho seguito i seguenti passaggi,

  1. Pulito e costruito il progetto in eclisse

  2. mvn clean install

  3. Tomcat riavviato

Stavo ancora affrontando lo stesso errore. Quindi ho pulito Tomcat, pulito la directory di lavoro di Tomcat e riavviato il server e il mio problema è scomparso. Spero che questo aiuti qualcuno


1

Per rispondere alla domanda originale. Secondo i documenti Java qui :

"NoSuchMethodError" Viene generato se un'applicazione tenta di chiamare un metodo specificato di una classe (statica o di istanza) e tale classe non ha più una definizione di quel metodo.

Normalmente, questo errore viene rilevato dal compilatore; questo errore può verificarsi solo in fase di esecuzione se la definizione di una classe è stata modificata in modo incompatibile.

  1. Se si verifica in fase di esecuzione, verificare che la classe contenente il metodo sia nel percorso di classe.
  2. Controlla se hai aggiunto una nuova versione di JAR e il metodo è compatibile.

1

Ho risolto questo problema in Eclipse rinominando un file di test Junit.
Nel mio spazio di lavoro Eclipse ho un progetto App e un progetto Test.
Il progetto Test ha il progetto App come progetto richiesto nel percorso di compilazione.

Iniziato a ottenere NoSuchMethodError.
Poi ho capito che la classe nel progetto Test aveva lo stesso nome della classe nel progetto App.

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

Dopo aver rinominato il Test con il nome corretto "ProjectionTest.java", l'eccezione è scomparsa.


Ho avuto un problema simile. Avevo una classe di dipendenza con lo stesso nome canonico completo. Dopo aver rinominato l'eccezione è andata via.
moralejaSinCuentoNiProverbio

1

Ho avuto lo stesso errore:

  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)

Per risolverlo ho controllato, in primo luogo, il diagramma di dipendenza del modulo ( click in your POM the combination -> Ctrl+Alt+Shift+Uo right click in your POM -> Maven -> Show dependencies) per capire dove si trovava esattamente il conflitto tra le librerie (Intelij IDEA). Nel mio caso particolare, avevo diverse versioni delle dipendenze di Jackson.

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

1) Quindi, ho aggiunto direttamente nel mio POM del progetto esplicitamente la versione più alta - 2.8.7 di questi due.

Nelle proprietà:

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

E come dipendenza:

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

2) Ma può anche essere risolto utilizzando le esclusioni di dipendenza .

Con lo stesso principio di seguito nell'esempio:

  <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>

La dipendenza da una versione indesiderata verrà esclusa dal progetto.


1

Nel mio caso avevo un progetto multi modulo e lo scenario era come se com.xyz.TestClassfosse nel modulo Ae così come nel modulo Be nel modulo Adipendeva dal modulo B. Quindi durante la creazione di un jar di assemblaggio penso che sia stata mantenuta solo una versione della classe se non si ha il metodo invocato, quindi ho ricevuto NoSuchMethodErrorun'eccezione di runtime, ma la compilazione andava bene.

Correlati: https://reflectoring.io/nosuchmethod/


0

Ho riscontrato un problema simile durante la modifica delle firme del metodo nella mia applicazione. La pulizia e la ricostruzione del mio progetto hanno risolto "NoSuchMethodError".


0

La risposta sopra spiega molto bene ... basta aggiungere una cosa Se stai usando eclipse usa ctrl + shift + T e inserisci la struttura del pacchetto di classe (es: gateway.smpp.PDUEventListener), troverai tutti i barattoli / progetti in cui è presente . Rimuovi i barattoli non necessari dal percorso di classe o aggiungi sopra nel percorso di classe. Ora raccoglierà quello corretto.


0

Ho riscontrato un problema simile.

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

Alla fine ho identificato la causa principale stava cambiando il tipo di dati della variabile.

  1. Employee.java-> Contiene la variabile ( EmpId) il cui tipo di dati è stato modificato da inta String.
  2. ReportGeneration.java-> Recupera il valore con il getter, getEmpId().

Dovremmo riorganizzare il barattolo includendo solo le classi modificate. Dato che non vi era alcun cambiamento, ReportGeneration.javaincludevo solo il Employee.classfile Jar. Ho dovuto includere il ReportGeneration.classfile nel vaso per risolvere il problema.


0

Ho avuto lo stesso problema. Ciò è causato anche quando c'è un'ambiguità nelle classi. Il mio programma stava tentando di invocare un metodo che era presente in due file JAR presenti nello stesso percorso / percorso di classe. Eliminare un file JAR o eseguire il codice in modo tale che venga utilizzato solo un file JAR. Verificare che non si stia utilizzando lo stesso JAR o versioni diverse dello stesso JAR che contengano la stessa classe.

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


0

Il più delle volte java.lang.NoSuchMethodError viene rilevato come compilatore ma a volte può verificarsi in fase di esecuzione. Se questo errore si verifica in fase di esecuzione, l'unica ragione potrebbe essere la modifica della struttura della classe che l'ha resa incompatibile.

Migliore spiegazione: https://www.journaldev.com/14538/java-lang-nosuchmethoderror


0

Ho riscontrato anche questo errore.

Il mio problema era che ho cambiato la firma di un metodo, qualcosa del genere

void invest(Currency money){...}

in

void invest(Euro money){...}

Questo metodo è stato invocato da un contesto simile a

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

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

Il compilatore non ha parlato di avvisi / errori, poiché il capitale è sia Valuta che Euro.

Il problema è apparso a causa del fatto che ho compilato solo la classe in cui è stato definito il metodo - Bank, ma non la classe da cui viene chiamato il metodo, che contiene il metodo main ().

Questo problema non è qualcosa che potresti riscontrare troppo spesso, poiché molto spesso il progetto viene ricostruito manualmente o un'azione di generazione viene attivata automaticamente, anziché semplicemente compilare una classe modificata.

La mia usecase era che avevo generato un file .jar che doveva essere usato come hotfix, che non conteneva App.class poiché non era stato modificato. Per me aveva senso non includerlo mentre mantenevo l'eredità della classe base dell'argomento iniziale.

Il fatto è che quando si compila una classe, il bytecode risultante è in qualche modo statico , in altre parole, è un riferimento rigido .

Il bytecode originale smontato (generato con lo strumento javap) è simile al seguente:

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

Dopo che ClassLoader ha caricato il nuovo Bank.class compilato, non troverà tale metodo, sembra che sia stato rimosso e non modificato, quindi l'errore indicato.

Spero che questo ti aiuti.


0

Nel mio caso il problema era avere due versioni della stessa libreria nel percorso di compilazione. La versione precedente della libreria non aveva la funzione e quella più recente lo aveva.


0

Ho avuto un problema simile con il mio progetto Gradle usando Intelij. L'ho risolto eliminando il pacchetto .gradle (vedi screenshot sotto) e ricostruendo il Progetto. Pacchetto .gradle


0

NoSuchMethodError: ho trascorso un paio d'ore a risolvere questo problema, finalmente risolto semplicemente rinominando il nome del pacchetto, ripulendolo e costruendolo ... Prova prima clean build se non funziona prova a rinominare il nome della classe o del nome del pacchetto e clean build .. .it dovrebbe essere riparato. In bocca al lupo.


-2

Se il nome del tuo file è diverso dal nome della classe che contiene il metodo principale, potrebbe essere la possibilità che questo errore possa causare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.