web-dev-qa-db-fra.com

Java "NoSuchMethodError"

Je suis en train: 

NoSuchMethodError: com.foo.SomeService.doSmth()Z

Ai-je bien compris que ce 'Z' signifie que le type de résultat de la méthode doSmth () est boolean? Si true, alors ce type de méthode n'existe vraiment pas car cette méthode renvoie une collection. Par contre, si j'appelle cette méthode, je n'assigne pas sa valeur de retour à une variable. J'appelle cette méthode comme ceci:

service.doSmth();

Des idées pourquoi cette erreur se produit? Tous les fichiers JAR nécessaires existent et toutes les autres méthodes de cette classe semblent exister. 

25
vrm

Il semble que la méthode existe dans classpath lors de la compilation, mais pas lors de l'exécution de votre application.

Je ne pense pas que le type de retour pose un problème. Si c'était le cas, il ne compilerait pas. Le compilateur génère une erreur lorsque l'appel de méthode est ambigu, et c'est le cas lorsque deux méthodes ne diffèrent que par le type de retour.

24
amorfis

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

En bref, un fichier de classe/jar au moment de l’exécution n’est pas le même que celui que vous avez utilisé lors de la compilation.

18
Bozho

C'est probablement une différence entre votre chemin de classe au moment de la compilation et votre chemin de classe au moment de l'exécution.

Voici ce qui semble se passer:

  • Le code est compilé avec un chemin de classe qui définit la méthode doSmth() renvoyant un booléen. Le code d'octet fait référence à la méthode doSmth()Z.
  • Au moment de l'exécution, la méthode doSmth()Z est introuvable. Une méthode renvoyant une collection est trouvée à la place.

Pour corriger ce problème, vérifiez votre chemin de classe (à la compilation).

16
Vivien Barousse

La réponse actuelle vous dit simplement pourquoi échoue. Il est généralement encore plus agréable de savoir comment résoudre les problèmes. Comme il est mentionné, le problème est généralement que vous avez construit votre programme mais lors de son exécution ou de son exportation, la bibliothèque n'est pas incluse. Donc, la solution est ...

Si vous êtes en cours d’exécution, vérifiez la configuration d’exécutionSélectionnez l’onglet Exécution -> Exécuter les configurations -> Sélectionnez la configuration que vous exécutez -> Vérifiez l’onglet Chemin de classe -> Assurez-vous que les bibliothèques dont vous avez besoin sont présentes

Si vous exportez (par exemple, un fichier war), suivez ceciSélectionnez un projet -> Sélectionnez des propriétés -> Sélectionnez un assemblage de déploiement -> Appuyez sur Ajouter -> Sélectionnez des entrées de chemin de construction Java -> Sélectionnez les bibliothèques dans lesquelles vous souhaitez être inclus votre fichier exporté (par exemple un fichier war)

Dans les deux cas, assurez-vous que la bibliothèque à laquelle vous faites référence est incluse.

Les autres problèmes fréquents liés à cette erreur ne sont pas le type de paramètres ou la visibilité appropriés, mais le compilateur détecte ensuite l'erreur avant de l'exécuter. Dans ce cas, vérifiez que la documentation correspond à la visibilité de la fonction et du package, et assurez-vous que la bibliothèque se trouve dans Chemin de construction Java dans les propriétés de votre projet.

4
Capagris

Peut-être que peut toujours aider quelqu'un, mais cette exception peut se produire également lorsque vous avez sur le chemin de classe deux classes dans des fichiers JAR différents qui ont la même signature mais n'ont pas les mêmes méthodes publiques.

Par exemple:

  • Dans le fichier mylibrary1.jar, vous avez la classe com.mypackage.mysubpackage.MyClass avec la méthode doSmth ()

  • Dans le fichier mylibrary2.jar, vous avez la classe com.mypackage.mysubpackage.MyClass without method doSmth ()

Lors de la recherche dans la classe, le chargeur de classes peut trouver d'abord mylibrary2.jar en fonction de la priorité du chemin, mais ne peut pas trouver la méthode sur cette classe.

Assurez-vous que vous n'avez pas le même paquet + classe sur deux fichiers différents.

3
dgisbert

J'ai remarqué que ce problème se produisait lors du test de modifications expérimentales dans plusieurs projets liés, après leur mise à jour à partir de SVN dans Eclipse. 

Plus précisément, j'ai mis à jour tous les projets à partir de SVN et rétabli le fichier .classpath plutôt que de le modifier manuellement pour que les choses restent simples. 

Ensuite, j'ai ré-ajouté les projets liés au chemin, mais j'ai oublié de supprimer les fichiers associés. C'est ainsi que le problème s'est produit pour moi. 

Donc, apparemment, le moteur d’exécution utilisait le fichier jar tandis que le compilateur utilisait les fichiers de projet.

2
ekangas

Une autre façon, cela peut arriver et est difficile à trouver:

Si la signature d'une méthode dans un fichier JAR externe change d'une manière telle qu'aucune erreur ne soit détectée dans le IDE, car elle est toujours compatible avec la façon dont vous l'appelez, la classe risque de ne pas être recompilée.

Si votre génération recherche les modifications dans les fichiers et les recompile seulement, il se peut que la classe ne soit pas recompilée pendant le processus de construction.

Donc, lorsque vous l'exécutez, cela peut entraîner ce problème. Bien que vous ayez le nouveau pot, votre propre code s’attend toujours à l’ancien mais ne se plaint jamais.

Pour rendre cela plus difficile, cela dépend de la JVM si elle peut gérer de tels cas. Donc, dans le pire des cas, il fonctionne sur le serveur de test mais pas sur la machine en direct.

0
Christian