Ricevo un NoSuchMethodError
errore durante l'esecuzione del mio programma Java. Cosa c'è che non va e come posso ripararlo?
Ricevo un NoSuchMethodError
errore durante l'esecuzione del mio programma Java. Cosa c'è che non va e come posso ripararlo?
Risposte:
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.
Caused by
sezione della traccia dello stack per trovare la classe / vaso colpevole
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".
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.
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]
...
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.
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 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 getDeclaredMethod
chiamata 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 TestUtilities
classe per estrarre campi per la verifica del test. (Generalmente con un codice legacy che non è stato progettato tenendo conto dei test unitari.)
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
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)
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.
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
.
Aggiungo solo alle risposte esistenti. Stavo affrontando questo problema con Tomcat in Eclipse. Avevo cambiato una classe e ho seguito i seguenti passaggi,
Pulito e costruito il progetto in eclisse
mvn clean install
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
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.
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 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+U
o 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.
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.
Nel mio caso avevo un progetto multi modulo e lo scenario era come se com.xyz.TestClass
fosse nel modulo A
e così come nel modulo B
e nel modulo A
dipendeva 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 NoSuchMethodError
un'eccezione di runtime, ma la compilazione andava bene.
Correlati: https://reflectoring.io/nosuchmethod/
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.
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.
Employee.java
-> Contiene la variabile ( EmpId
) il cui tipo di dati è stato modificato da int
a String
.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.java
includevo solo il Employee.class
file Jar. Ho dovuto includere il ReportGeneration.class
file nel vaso per risolvere il problema.
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)]
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
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.
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
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.
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.