¿Cómo soluciono un NoSuchMethodError?

178

Recibo un NoSuchMethodErrorerror al ejecutar mi programa Java. ¿Qué pasa y cómo lo soluciono?

John Meagher
fuente
11
En Netbeans: haga clic derecho en el proyecto en la pestaña Proyectos, use "Limpiar y compilar". Lo resolvió por mí.
Heinzlmaen
3
También en Intellij Idea, la reconstrucción resuelve el problema a veces
Hawk
1
Este artículo es muy útil para este tema reflectoring.io/nosuchmethod
Michael Smith

Respuestas:

228

Sin más información, es difícil determinar el problema, pero la causa principal es que probablemente compiló una clase contra una versión diferente de la clase a la que le falta un método, que el que está utilizando al ejecutarlo.

Mire el seguimiento de la pila ... Si la excepción aparece cuando se llama a un método en un objeto en una biblioteca, lo más probable es que esté usando versiones separadas de la biblioteca al compilar y ejecutar. Asegúrese de tener la versión correcta en ambos lugares.

Si la excepción aparece cuando se llama a un método en objetos instanciados por clases que realizó, entonces su proceso de compilación parece ser defectuoso. Asegúrese de que los archivos de clase que está ejecutando estén actualizados cuando compila.

Vetle
fuente
3
Recientemente descubrimos la causa de uno de estos y resultó que el proceso de compilación estaba poniendo los archivos de clase en su lugar antes de que se cerrara el servidor Java, y lo golpeamos porque el servidor Java no había cargado algunas clases, y luego se cargó algunos pero obtuvieron estos nuevos, y dado que el nuevo código se refería a métodos que las clases anteriores no tenían ... bingo, NoSuchMethodError
vazor
"Mira el seguimiento de la pila ..." - Bueno, casi siempre voy y reviso la última Caused bysección en el seguimiento de la pila para encontrar la clase / jarra culpable
KrishPrabakar
108

Estaba teniendo tu problema, y ​​así es como lo solucioné. Los siguientes pasos son una forma de trabajo para agregar una biblioteca. Había hecho los dos primeros pasos correctamente, pero no había hecho el último arrastrando el archivo ".jar" directamente desde el sistema de archivos a la carpeta "lib" en mi proyecto eclipse. Además, tuve que eliminar la versión anterior de la biblioteca tanto de la ruta de compilación como de la carpeta "lib".

Paso 1: agrega .jar a la ruta de compilación

ingrese la descripción de la imagen aquí

Paso 2: fuentes asociadas y javadocs (opcional)

ingrese la descripción de la imagen aquí

Paso 3 - En realidad, arrastre el archivo .jar a la carpeta "lib" (no opcional)

ingrese la descripción de la imagen aquí

Chris Dutrow
fuente
75
+1 para "Todo el mundo espera que sepas cómo usarlo y, si no lo haces, rechazarán tu pregunta".
Vikram
73

Tenga en cuenta que en el caso de la reflexión, obtiene un NoSuchMethodException, mientras que con el código no reflexivo, obtiene NoSuchMethodError. Tiendo a mirar en lugares muy diferentes cuando me enfrento a uno versus el otro.

erickson
fuente
En otras palabras, está diciendo que si está utilizando la reflexión para obtener un método en una clase y no se encuentra el método, obtendrá una NoSuchMethodException. Pero si se encuentra en un escenario en el que compiló su código contra algunas bibliotecas y en el servidor tiene otras bibliotecas (tal vez más nuevas o más antiguas), obtiene el NoSuchMethodError. Corrígeme si me equivoco.
Victor
Eso es correcto, @Victor
KrishPrabakar
51

Si tiene acceso para cambiar los parámetros de JVM, agregar resultados detallados debería permitirle ver qué clases se están cargando desde qué archivos JAR.

java -verbose:class <other args>

Cuando se ejecuta su programa, la JVM debe volcar a información estándar como:

...

[Junit.framework.Assert cargado del archivo: / C: /Program%20Files/junit3.8.2/junit.jar]

...

mate b
fuente
3
+1 ¡Brillante! Resolví un pequeño problema desagradable usando este método, gracias. Esta es una excelente manera de descubrir cuándo las clases se han infiltrado en un classpath de alguna manera.
Duncan Jones
1
+1 ¡Me salvaste el día! Era solo una biblioteca que incluía clases antiguas con los mismos nombres en sus fuentes.
Andrii Nemchenko
12

Esto generalmente se produce cuando se usa un sistema de compilación como Apache Ant que solo compila archivos java cuando el archivo java es más nuevo que el archivo de clase. Si la firma de un método cambia y las clases usaban la versión anterior, es posible que las cosas no se compilen correctamente. La solución habitual es hacer una reconstrucción completa (generalmente "ant clean" y luego "ant").

Algunas veces esto también puede ser causado cuando se compila contra una versión de una biblioteca pero se ejecuta contra una versión diferente.

John Meagher
fuente
1
En realidad, esto se parece más a un problema que surge para los programadores de Java que usan cualquier marco de desarrollo de Java: Maven, NetBeans y Apache Ant, como puede ver en todas las respuestas aquí.
HoldOffHunger
8

Si usa Maven u otro marco, y obtiene este error casi al azar, intente una instalación limpia como ...

clean install

Es especialmente probable que esto funcione si escribió el objeto y sabe que tiene el método. Trabajó para mi.

HoldOffHunger
fuente
Este es también el caso de las compilaciones de Gradle.
Jonathan Landrum el
4

Esto también puede ser el resultado del uso de la reflexión. Si tiene un código que se refleja en una clase y extrae un método por nombre (por ejemplo: con Class.getDeclaredMethod("someMethodName", .....)), cada vez que cambie el nombre del método, como durante un refactorizador, deberá recordar actualizar los parámetros al método de reflexión para que coincida con el nueva firma del método, o la getDeclaredMethodllamada arrojará un NoSuchMethodException.

Si esta es la razón, entonces el seguimiento de la pila debería mostrar el punto en que se invoca el método de reflexión, y solo necesitará actualizar los parámetros para que coincidan con la firma del método real.

En mi experiencia, esto surge ocasionalmente cuando la unidad prueba métodos / campos privados y usa una TestUtilitiesclase para extraer campos para la verificación de pruebas. (Generalmente con código heredado que no fue diseñado teniendo en cuenta las pruebas unitarias).

rcreswick
fuente
3

Si está escribiendo una aplicación web, asegúrese de no tener versiones conflictivas de un jar en el directorio de la biblioteca global de su contenedor y también en su aplicación. Es posible que no sepa qué jar está utilizando el cargador de clases.

p.ej

  • tomcat / common / lib
  • mywebapp / WEB-INF / lib
Cheekysoft
fuente
2

Estos problemas son causados ​​por el uso del mismo objeto en las mismas dos clases. Los objetos utilizados no contienen un nuevo método que se ha agregado que contiene la nueva clase de objeto.

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$ 

Estos problemas son causados ​​por la clase similar 02 concomitante (1 en src, 1 en el archivo jar aquí es gateway.jar)

Quảng Trường Thời Đại
fuente
2

Significa que el método respectivo no está presente en la clase:

  1. Si está utilizando jar, descompile y compruebe si la versión respectiva de jar tiene la clase adecuada.
  2. Compruebe si ha compilado la clase adecuada de su fuente.
Shrikant
fuente
2

Para mí sucedió porque cambié el tipo de argumento en la función, de Objeto a, a Cadena a. Podría resolverlo con clean y construir de nuevo

Tito
fuente
2

Acabo de resolver este error al reiniciar mi Eclipse y ejecutar la aplicación. La razón de mi caso puede ser porque reemplazo mis archivos fuente sin cerrar mi proyecto o Eclipse. Lo que causó una versión diferente de las clases que estaba usando.

Ryan Luo Xu
fuente
2

Pruebe de esta manera: elimine todos los archivos .class en los directorios de su proyecto (y, por supuesto, todos los subdirectorios). Reconstruir.

A veces mvn clean(si está utilizando Maven) no limpia los archivos .class creados manualmente por javac. Y esos archivos antiguos contienen firmas antiguas, lo que lleva a NoSuchMethodError.

WHOIF
fuente
2

Solo agregando a las respuestas existentes. Estaba enfrentando este problema con tomcat en eclipse. Había cambiado una clase e hice los siguientes pasos,

  1. Limpié y construyó el proyecto en eclpise

  2. instalación limpia de mvn

  3. Tomcat reiniciado

Aún así me enfrentaba al mismo error. Luego limpié tomcat, limpié el directorio de trabajo de tomcat y reinicié el servidor y mi problema desapareció. Espero que esto ayude a alguien

Code_Mode
fuente
1

Para responder la pregunta original. De acuerdo con los documentos de Java aquí :

"NoSuchMethodError" Se genera si una aplicación intenta llamar a un método específico de una clase (ya sea estática o instancia), y esa clase ya no tiene una definición de ese método.

Normalmente, este error es detectado por el compilador; Este error solo puede ocurrir en tiempo de ejecución si la definición de una clase ha cambiado de manera incompatible.

  1. Si sucede en el tiempo de ejecución, verifique que la clase que contiene el método esté en la ruta de clase.
  2. Compruebe si ha agregado una nueva versión de JAR y si el método es compatible.
Reachgoals
fuente
1

Solucioné este problema en Eclipse cambiando el nombre de un archivo de prueba Junit.
En mi espacio de trabajo de Eclipse tengo un proyecto de aplicación y un proyecto de prueba.
El proyecto de prueba tiene el proyecto de la aplicación como un proyecto requerido en la ruta de compilación.

Comenzó a obtener el NoSuchMethodError.
Luego me di cuenta de que la clase en el proyecto de prueba tenía el mismo nombre que la clase en el proyecto de la aplicación.

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

Después de cambiar el nombre de la prueba al nombre correcto "ProjectionTest.java", la excepción desapareció.

Dave Inlow
fuente
Tuve un problema similar Tenía una clase de dependencia con el mismo nombre canónico completo. Después de renombrar, la excepción desapareció.
moralejaSinCuentoNiProverbio
1

Yo tenía el mismo error:

  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)

Para resolverlo, verifiqué, en primer lugar, el Diagrama de dependencia del módulo ( click in your POM the combination -> Ctrl+Alt+Shift+Uo right click in your POM -> Maven -> Show dependencies) para comprender dónde estaba exactamente el conflicto entre bibliotecas (Intelij IDEA). En mi caso particular, tenía diferentes versiones de las dependencias de Jackson.

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

1) Entonces, agregué directamente en mi POM del proyecto explícitamente la versión más alta: 2.8.7 de estos dos.

En propiedades:

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

Y como dependencia:

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

2) Pero también se puede resolver usando Exclusiones de dependencia .

Por el mismo principio que a continuación en el ejemplo:

  <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 dependencia con la versión no deseada se excluirá de su proyecto.

invzbl3
fuente
1

En mi caso, tenía un proyecto de varios módulos y el escenario era como si com.xyz.TestClassestuviera en el módulo Ay, además, en el módulo By el módulo Adependía del módulo B. Entonces, al crear un jar de ensamblaje, creo que solo se retuvo una versión de la clase si eso no tiene el método invocado, entonces estaba obteniendoNoSuchMethodError excepción de tiempo de ejecución, pero la compilación estuvo bien.

Relacionado: https://reflectoring.io/nosuchmethod/

Gaurav Khare
fuente
0

Me encontré con un problema similar cuando estaba cambiando las firmas de métodos en mi aplicación. Limpiar y reconstruir mi proyecto resolvió el "NoSuchMethodError".

caballero
fuente
0

La respuesta anterior explica muy bien ... solo para agregar una cosa Si está usando eclipse, use ctrl + shift + T e ingrese la estructura de paquete de la clase (por ejemplo: gateway.smpp.PDUEventListener), encontrará todos los frascos / proyectos donde está presente . Elimine los tarros innecesarios de classpath o agregue arriba en class path. Ahora recogerá el correcto.

Príncipe
fuente
0

Me encontré con un problema similar.

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

Finalmente identifiqué que la causa raíz estaba cambiando el tipo de datos de la variable.

  1. Employee.java-> Contiene la variable ( EmpId) cuyo tipo de datos se ha cambiado de inta String.
  2. ReportGeneration.java-> Recupera el valor con el captador, getEmpId().

Se supone que debemos reempaquetar el jar incluyendo solo las clases modificadas. Como no hubo cambios ReportGeneration.java, solo Employee.classincluí el archivo Jar. Tuve que incluir el ReportGeneration.classarchivo en el jar para resolver el problema.

AnonymousCoder
fuente
0

He tenido el mismo problema Esto también se produce cuando hay una ambigüedad en las clases. Mi programa intentaba invocar un método que estaba presente en dos archivos JAR presentes en la misma ubicación / ruta de clase. Elimine un archivo JAR o ejecute su código de modo que solo se use un archivo JAR. Compruebe que no está utilizando el mismo JAR o diferentes versiones del mismo JAR que contienen la misma clase.

DISP_E_EXCEPTION [paso] [] [Z-JAVA-105 Excepción de Java java.lang.NoSuchMethodError (com.example.yourmethod)]

ShankarDaruga
fuente
0

La mayoría de las veces se captura java.lang.NoSuchMethodError en el compilador, pero a veces puede ocurrir en tiempo de ejecución. Si este error ocurre en tiempo de ejecución, la única razón podría ser el cambio en la estructura de clases que lo hizo incompatible.

Mejor explicación: https://www.journaldev.com/14538/java-lang-nosuchmethoderror

Yash P Shah
fuente
0

También he encontrado este error.

Mi problema fue que he cambiado la firma de un método, algo así como

void invest(Currency money){...}

dentro

void invest(Euro money){...}

Este método fue invocado desde un contexto similar a

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

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

El compilador guardó silencio con respecto a las advertencias / errores, ya que el capital es tanto moneda como euro.

El problema apareció debido al hecho de que solo compilé la clase en la que se definió el método: Bank, pero no la clase desde la que se llama al método, que contiene el método main ().

Este problema no es algo que pueda encontrar con demasiada frecuencia, ya que con mayor frecuencia el proyecto se reconstruye manualmente o se activa automáticamente una acción de compilación, en lugar de solo compilar la clase modificada.

Mi caso de uso fue que generé un archivo .jar que iba a usarse como un hotfix, que no contenía la App.class ya que no se modificó. Tenía sentido para mí no incluirlo, ya que mantuve la herencia básica de la clase base del argumento inicial.

La cuestión es que, cuando compila una clase, el bytecode resultante es algo estático , en otras palabras, es una referencia difícil .

El bytecode original desmontado (generado con la herramienta javap) se ve así:

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

Después de que ClassLoader carga el nuevo Bank.class compilado, no encontrará dicho método, parece que se eliminó y no se modificó, por lo tanto, el error con nombre.

Espero que esto ayude.

Mihai Savin
fuente
0

El problema en mi caso era tener dos versiones de la misma biblioteca en la ruta de compilación. La versión anterior de la biblioteca no tenía la función, y la nueva sí.

KK
fuente
0

Tuve un problema similar con mi Proyecto Gradle usando Intelij. Lo resolví eliminando el paquete .gradle (ver captura de pantalla a continuación) y reconstruyendo el Proyecto. Paquete .gradle

J.Orlando
fuente
0

NoSuchMethodError: He pasado un par de horas solucionando este problema, finalmente lo solucioné simplemente renombrando el nombre del paquete, limpiando y compilando ... Intenta limpiar primero si no funciona, intenta renombrar el nombre de la clase o el nombre del paquete y limpia la compilación ... . debería ser reparado. Buena suerte.

Shirish Singh
fuente
-2

Si el nombre de su archivo es diferente al nombre de la clase que contiene el método principal, entonces es posible que este error pueda causar.

Amit Walke
fuente