Comment corriger une erreur NoSuchMethodError?


178

J'obtiens une NoSuchMethodErrorerreur lors de l'exécution de mon programme Java. Quel est le problème et comment le résoudre?


11
Dans Netbeans: Faites un clic droit sur le projet dans l'onglet Projets, utilisez "Nettoyer et construire". Résolu pour moi.
Heinzlmaen

3
Aussi dans Intellij Idea, reconstruire résout parfois le problème
Hawk

1
Cet article est très utile pour ce numéro reflectoring.io/nosuchmethod
Michael Smith

Réponses:


228

Sans plus d'informations, il est difficile d'identifier le problème, mais la cause première est que vous avez probablement compilé une classe contre une version différente de la classe à laquelle une méthode manque, que celle que vous utilisez lors de son exécution.

Regardez la trace de la pile ... Si l'exception apparaît lors de l'appel d'une méthode sur un objet dans une bibliothèque, vous utilisez probablement des versions distinctes de la bibliothèque lors de la compilation et de l'exécution. Assurez-vous d'avoir la bonne version aux deux endroits.

Si l'exception apparaît lors de l'appel d'une méthode sur des objets instanciés par les classes que vous avez créées, votre processus de construction semble être défectueux. Assurez-vous que les fichiers de classe que vous exécutez réellement sont mis à jour lors de la compilation.


3
Nous avons récemment découvert la cause de l'un d'entre eux et il s'est avéré que le processus de construction mettait les fichiers de classe en place avant que le serveur java ne soit arrêté, et nous avons rencontré ce problème parce que le serveur java n'avait pas chargé certaines classes, puis il s'est chargé certains mais il en a eu de nouveaux, et comme le nouveau code faisait référence à des méthodes que les anciennes classes n'avaient pas ... bingo, NoSuchMethodError
vazor

"Regardez la trace de la pile ..." - Eh bien, je vais presque toujours vérifier la dernière Caused bysection de la trace de la pile pour trouver la classe / le pot coupable
KrishPrabakar le

108

J'avais votre problème et c'est ainsi que je l'ai résolu. Les étapes suivantes constituent une méthode de travail pour ajouter une bibliothèque. J'avais bien fait les deux premières étapes, mais je n'avais pas fait la dernière en faisant glisser le fichier ".jar" directement du système de fichiers dans le dossier "lib" de mon projet eclipse. De plus, j'ai dû supprimer la version précédente de la bibliothèque à la fois du chemin de construction et du dossier «lib».

Étape 1 - Ajouter .jar au chemin de construction

entrez la description de l'image ici

Étape 2 - Associer des sources et des javadocs (facultatif)

entrez la description de l'image ici

Étape 3 - Faites glisser le fichier .jar dans le dossier "lib" (non facultatif)

entrez la description de l'image ici


75
+1 pour "Tout le monde s'attend à ce que vous sachiez comment l'utiliser et si vous ne le faites pas, ils voteront contre votre question."
Vikram

73

Notez que dans le cas de la réflexion, vous obtenez un NoSuchMethodException, tandis qu'avec un code non réfléchissant, vous obtenez NoSuchMethodError. J'ai tendance à chercher dans des endroits très différents lorsque je suis confronté à l'un par rapport à l'autre.


En d'autres termes, vous dites que si vous utilisez la réflexion pour obtenir une méthode sur une classe et que la méthode n'est pas trouvée, vous obtenez une NoSuchMethodException. Mais si vous êtes dans un scénario lorsque vous avez compilé votre code avec certaines bibliothèques et que sur le serveur vous avez d'autres bibliothèques (peut-être plus récentes peut-être plus anciennes), vous obtenez le NoSuchMethodError. Corrige moi si je me trompe.
Victor

C'est exact, @Victor
KrishPrabakar le

51

Si vous avez le droit de modifier les paramètres JVM, l'ajout d'une sortie détaillée devrait vous permettre de voir quelles classes sont chargées à partir de quels fichiers JAR.

java -verbose:class <other args>

Lorsque votre programme est exécuté, la machine virtuelle Java doit vider les informations standard telles que:

...

[Chargé junit.framework.Assert à partir du fichier: / C: /Program%20Files/junit3.8.2/junit.jar]

...


3
+1 Brillant! J'ai résolu un petit problème méchant en utilisant cette méthode, merci. C'est un excellent moyen de découvrir quand les classes se sont faufilées sur un chemin de classe.
Duncan Jones

1
+1 Vous avez sauvé ma journée! C'était juste une bibliothèque qui incluait d'anciennes classes avec les mêmes noms dans ses sources.
Andrii Nemchenko

12

Cela est généralement dû à l'utilisation d'un système de construction comme Apache Ant qui ne compile les fichiers java que lorsque le fichier java est plus récent que le fichier de classe. Si une signature de méthode change et que les classes utilisaient l'ancienne version, les choses peuvent ne pas être compilées correctement. Le correctif habituel est de faire une reconstruction complète (généralement "ant clean" puis "ant").

Parfois, cela peut également être causé lors de la compilation avec une version d'une bibliothèque mais avec une version différente.


1
En fait, cela ressemble plus à un problème qui se pose aux programmeurs Java qui utilisent n'importe quel framework de développement Java: Maven, NetBeans et Apache Ant, comme vous pouvez le voir dans toutes les réponses ici.
HoldOffHunger

8

Si vous utilisez Maven ou un autre framework et que vous obtenez cette erreur presque au hasard, essayez une installation propre comme ...

clean install

Ceci est particulièrement susceptible de fonctionner si vous avez écrit l'objet et que vous savez qu'il possède la méthode. A travaillé pour moi.


C'est également le cas pour les builds Gradle.
Jonathan Landrum

4

Cela peut également être le résultat de l'utilisation de la réflexion. Si vous avez du code qui réfléchit sur une classe et extrait une méthode par son nom (par exemple: avec Class.getDeclaredMethod("someMethodName", .....)), à chaque fois que le nom de la méthode change, comme lors d'un refactor, vous devrez vous rappeler de mettre à jour les paramètres de la méthode de réflexion pour correspondre à la nouvelle signature de méthode, ou l' getDeclaredMethodappel lancera un NoSuchMethodException.

Si c'est la raison, alors la trace de pile doit montrer le point où la méthode de réflexion est appelée, et vous aurez juste besoin de mettre à jour les paramètres pour correspondre à la signature de méthode réelle.

D'après mon expérience, cela se produit parfois lors des tests unitaires de méthodes / champs privés et de l'utilisation d'une TestUtilitiesclasse pour extraire des champs pour la vérification des tests. (Généralement avec du code hérité qui n'a pas été conçu pour les tests unitaires.)


3

Si vous écrivez une application Web, assurez-vous que vous n'avez pas de versions conflictuelles d'un fichier jar dans le répertoire de la bibliothèque globale de votre conteneur et également dans votre application. Vous ne savez peut-être pas nécessairement quel fichier jar est utilisé par le chargeur de classe.

par exemple

  • tomcat / commun / lib
  • mywebapp / WEB-INF / lib

2

Ces problèmes sont causés par l'utilisation du même objet dans les deux mêmes classes. Les objets utilisés ne contiennent pas de nouvelle méthode a été ajoutée que la nouvelle classe d'objets contient.

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$ 

Ces problèmes sont causés par la classe similaire 02 concomitante (1 dans src, 1 dans le fichier jar, ici gateway.jar)


2

Cela signifie que la méthode respective n'est pas présente dans la classe:

  1. Si vous utilisez jar, décompilez et vérifiez si la version respective de jar a la classe appropriée.
  2. Vérifiez si vous avez compilé la classe appropriée à partir de votre source.

2

Pour moi, cela s'est produit parce que j'ai changé le type d'argument dans la fonction, de Object a, à String a. Je pourrais le résoudre avec nettoyer et reconstruire


2

Je viens de résoudre cette erreur en redémarrant mon Eclipse et en exécutant l'application. La raison de mon cas peut être que je remplace mes fichiers source sans fermer mon projet ou Eclipse. Ce qui a causé une version différente des classes que j'utilisais.


2

Essayez de cette façon: supprimez tous les fichiers .class des répertoires de votre projet (et, bien sûr, tous les sous-répertoires). Reconstruire.

Parfois mvn clean(si vous utilisez maven) ne nettoie pas les fichiers .class créés manuellement par javac. Et ces anciens fichiers contiennent d'anciennes signatures, ce qui conduit à NoSuchMethodError.


2

Juste ajouter aux réponses existantes. J'étais confronté à ce problème avec tomcat en éclipse. J'avais changé de classe et suivi les étapes suivantes,

  1. Nettoyé et construit le projet dans éclpise

  2. installation propre mvn

  3. Tomcat redémarré

J'étais toujours confronté à la même erreur. Ensuite, j'ai nettoyé tomcat, nettoyé le répertoire de travail de tomcat et redémarré le serveur et mon problème est parti. J'espère que cela aide quelqu'un


1

Pour répondre à la question initiale. Selon la documentation java ici :

"NoSuchMethodError" Lancé si une application tente d'appeler une méthode spécifiée d'une classe (statique ou instance) et que cette classe n'a plus de définition de cette méthode.

Normalement, cette erreur est interceptée par le compilateur; cette erreur ne peut se produire au moment de l'exécution que si la définition d'une classe a été modifiée de manière incompétente.

  1. Si cela se produit pendant l'exécution, vérifiez que la classe contenant la méthode est dans le chemin de la classe.
  2. Vérifiez si vous avez ajouté une nouvelle version de JAR et que la méthode est compatible.

1

J'ai résolu ce problème dans Eclipse en renommant un fichier de test Junit.
Dans mon espace de travail Eclipse, j'ai un projet d'application et un projet de test.
Le projet de test a le projet d'application comme projet obligatoire sur le chemin de génération.

Commencé à obtenir le NoSuchMethodError.
Ensuite, j'ai réalisé que la classe du projet Test avait le même nom que la classe du projet App.

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

Après avoir renommé le test avec le nom correct "ProjectionTest.java", l'exception a disparu.


J'ai eu un problème similaire. J'avais une classe de dépendance avec le même nom canonique complet. Après avoir renommé l'exception a disparu.
moraljaSinCuentoNiProverbio

1

J'ai eu la même erreur:

  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)

Pour le résoudre, j'ai vérifié, dans un premier temps, le diagramme de dépendance des modules ( click in your POM the combination -> Ctrl+Alt+Shift+Uou right click in your POM -> Maven -> Show dependencies) pour comprendre où se situait exactement le conflit entre les bibliothèques (Intelij IDEA). Dans mon cas particulier, j'avais différentes versions des dépendances de Jackson.

entrez la description de l'image ici entrez la description de l'image ici

1) J'ai donc ajouté directement dans mon POM du projet explicitement la version la plus élevée - 2.8.7 de ces deux.

Dans les propriétés:

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

Et comme dépendance:

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

2) Mais il peut également être résolu en utilisant les exclusions de dépendances .

Par le même principe que ci-dessous dans l'exemple:

  <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 dépendance avec une version indésirable sera exclue de votre projet.


1

Dans mon cas, j'avais un projet multi-module et le scénario était comme com.xyz.TestClassdans le module Aet ainsi que dans le module Bet le module Adépendait du module B. Ainsi, lors de la création d'un fichier d'assemblage, je pense qu'une seule version de la classe a été conservée si elle n'a pas la méthode invoquée, alors j'obtenaisNoSuchMethodError une exception d'exécution, mais la compilation était bien.

En relation: https://reflectoring.io/nosuchmethod/


0

J'ai rencontré un problème similaire lorsque je changeais les signatures de méthode dans mon application. Le nettoyage et la reconstruction de mon projet ont résolu le "NoSuchMethodError".


0

La réponse ci-dessus explique très bien ... juste pour ajouter une chose Si vous utilisez eclipse, utilisez ctrl + shift + T et entrez la structure du package de la classe (par exemple: gateway.smpp.PDUEventListener), vous trouverez tous les jars / projets où il est présent . Supprimez les fichiers JAR inutiles du chemin de classe ou ajoutez ci-dessus dans le chemin de classe. Maintenant, il en choisira une.


0

J'ai rencontré un problème similaire.

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

Enfin, j'ai identifié la cause première du changement du type de données de la variable.

  1. Employee.java-> Contient la variable ( EmpId) dont le type de données a été changé de intàString .
  2. ReportGeneration.java-> Récupère la valeur à l' aide du getter, getEmpId().

Nous sommes censés réorganiser le fichier jar en n'incluant que les classes modifiées. Comme il n'y avait pas de changement, ReportGeneration.javaj'incluais uniquement le Employee.classfichier Jar. J'ai dû inclure le ReportGeneration.classfichier dans le pot pour résoudre le problème.


0

J'ai eu le même problème. Cela se produit également lorsqu'il y a une ambiguïté dans les classes. Mon programme essayait d'appeler une méthode qui était présente dans deux fichiers JAR présents au même emplacement / chemin de classe. Supprimez un fichier JAR ou exécutez votre code de telle sorte qu'un seul fichier JAR soit utilisé. Vérifiez que vous n'utilisez pas le même JAR ou des versions différentes du même JAR contenant la même classe.

DISP_E_EXCEPTION [étape] [] [Exception Java Z-JAVA-105 java.lang.NoSuchMethodError (com.example.yourmethod)]


0

La plupart du temps, java.lang.NoSuchMethodError est intercepté par le compilateur, mais parfois cela peut se produire à l'exécution. Si cette erreur se produit au moment de l'exécution, la seule raison pourrait être la modification de la structure de classe qui l'a rendue incompatible.

Meilleure explication: https://www.journaldev.com/14538/java-lang-nosuchmethoderror


0

J'ai aussi rencontré cette erreur.

Mon problème était que j'ai changé la signature d'une méthode, quelque chose comme

void invest(Currency money){...}

dans

void invest(Euro money){...}

Cette méthode a été invoquée à partir d'un contexte similaire à

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

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

Le compilateur a gardé le silence en ce qui concerne les avertissements / erreurs, car le capital est à la fois monnaie et euro.

Le problème est apparu du fait que je n'ai compilé que la classe dans laquelle la méthode a été définie - Bank, mais pas la classe à partir de laquelle la méthode est appelée, qui contient la méthode main ().

Ce problème n'est pas quelque chose que vous pourriez rencontrer trop souvent, car le plus souvent, le projet est reconstruit manuellement ou une action de construction est déclenchée automatiquement, au lieu de simplement compiler la classe modifiée.

Mon cas d'utilisation était que j'ai généré un fichier .jar qui devait être utilisé comme correctif, qui ne contenait pas l'App.class car il n'a pas été modifié. Cela me paraissait logique de ne pas l'inclure car je conservais l'héritage de classe de base de l'argument initial.

Le fait est que lorsque vous compilez une classe, le bytecode résultant est un peu statique , en d'autres termes, c'est une référence dure .

Le bytecode démonté d'origine (généré avec l'outil javap) ressemble à ceci:

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

Une fois que le ClassLoader a chargé la nouvelle Bank.class compilée, il ne trouvera pas une telle méthode, il apparaît comme si elle a été supprimée et non modifiée, d'où l'erreur nommée.

J'espère que cela t'aides.


0

Le problème dans mon cas était d'avoir deux versions de la même bibliothèque dans le chemin de construction. L'ancienne version de la bibliothèque n'avait pas la fonction, et la plus récente en avait.


0

J'ai eu un problème similaire avec mon projet Gradle en utilisant Intelij. Je l'ai résolu en supprimant le package .gradle (voir capture d'écran ci-dessous) et en reconstruisant le projet. Paquet .gradle


0

NoSuchMethodError: J'ai passé quelques heures à résoudre ce problème, je l'ai finalement résolu en renommant simplement le nom du package, en le nettoyant et en le compilant ... Essayez d'abord la construction propre si cela ne fonctionne pas, essayez de renommer le nom de la classe ou le nom du package et la construction propre. .il devrait être corrigé. Bonne chance.


-2

Si le nom de votre fichier est différent du nom de la classe qui contient la méthode principale, il se peut que cette erreur puisse provoquer.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.