J'obtiens une NoSuchMethodError
erreur lors de l'exécution de mon programme Java. Quel est le problème et comment le résoudre?
J'obtiens une NoSuchMethodError
erreur lors de l'exécution de mon programme Java. Quel est le problème et comment le résoudre?
Réponses:
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.
Caused by
section de la trace de la pile pour trouver la classe / le pot coupable
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».
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.
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]
...
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.
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.
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' getDeclaredMethod
appel 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 TestUtilities
classe 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.)
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
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)
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.
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
.
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,
Nettoyé et construit le projet dans éclpise
installation propre mvn
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
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.
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 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+U
ou 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.
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.
Dans mon cas, j'avais un projet multi-module et le scénario était comme com.xyz.TestClass
dans le module A
et ainsi que dans le module B
et le module A
dé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/
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.
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.
Employee.java
-> Contient la variable ( EmpId
) dont le type de données a été changé de int
àString
.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.java
j'incluais uniquement le Employee.class
fichier Jar. J'ai dû inclure le ReportGeneration.class
fichier dans le pot pour résoudre le problème.
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)]
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
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.
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
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.
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.