Como faço para corrigir um NoSuchMethodError?

178

Estou recebendo um NoSuchMethodErrorerro ao executar meu programa Java. O que há de errado e como corrigi-lo?

John Meagher
fonte
11
No Netbeans: clique com o botão direito do mouse no projeto na guia Projetos, use "Limpar e criar". Resolvi isso para mim.
Heinzlmaen 20/01
3
Também em IntelliJ IDEA, reconstruir resolve o problema às vezes
Falcão
1
Este artigo é muito útil para esta questão reflectoring.io/nosuchmethod
Michael Smith

Respostas:

228

Sem mais informações, é difícil identificar o problema, mas a causa principal é que você provavelmente compilou uma classe com uma versão diferente da classe que está faltando um método, além da que você está usando ao executá-lo.

Observe o rastreamento da pilha ... Se a exceção aparecer ao chamar um método em um objeto em uma biblioteca, é provável que você esteja usando versões separadas da biblioteca ao compilar e executar. Verifique se você tem a versão correta nos dois lugares.

Se a exceção aparecer ao chamar um método em objetos instanciados pelas classes que você criou, seu processo de compilação parece estar com defeito. Verifique se os arquivos de classe que você está realmente executando são atualizados ao compilar.

Vetle
fonte
3
Recentemente, descobrimos a causa de uma delas, e o processo de compilação estava colocando os arquivos de classe no lugar antes que o servidor java fosse desligado, e atingimos isso porque o servidor java não carregava algumas classes e carregava alguns, mas tem esses novos, e uma vez que o novo código se refere aos métodos que as velhas classes não têm ... bingo, NoSuchMethodError
vazor
"Olhe para o rastreamento de pilha ..." - Bem, eu quase sempre vou verificar a última Caused byseção no rastreamento de pilha para encontrar a classe / jar
culpada
108

Eu estava tendo seu problema, e foi assim que eu o corrigi. As etapas a seguir são uma maneira prática de adicionar uma biblioteca. Eu tinha feito os dois primeiros passos corretamente, mas não o último, arrastando o arquivo ".jar" diretamente do sistema de arquivos para a pasta "lib" no meu projeto eclipse. Além disso, eu tive que remover a versão anterior da biblioteca do caminho de compilação e da pasta "lib".

Etapa 1 - adicione .jar para criar o caminho

insira a descrição da imagem aqui

Etapa 2 - Associar fontes e javadocs (opcional)

insira a descrição da imagem aqui

Etapa 3 - Arraste o arquivo .jar para a pasta "lib" (não opcional)

insira a descrição da imagem aqui

Chris Dutrow
fonte
75
+1 em "Todo mundo espera que você saiba como usá-lo e, se não o fizer, eles rebaixam sua pergunta".
Vikram
73

Observe que, no caso de reflexão, você recebe um NoSuchMethodException, enquanto que com código não reflexivo, recebe NoSuchMethodError. Costumo procurar em lugares muito diferentes quando confrontados com um contra o outro.

erickson
fonte
Em outras palavras, você está dizendo que, se você estiver usando reflexão para obter um método em uma classe e o método não for encontrado, você receberá uma NoSuchMethodException. Mas se você estiver em um cenário em que compilou seu código em algumas bibliotecas e no servidor possui outras (talvez mais novas talvez mais antigas), você recebe o NoSuchMethodError. Corrija-me se eu estiver errado.
Victor
Está correto, @Victor
KrishPrabakar
51

Se você tiver acesso para alterar os parâmetros da JVM, a inclusão de saída detalhada deve permitir que você veja quais classes estão sendo carregadas a partir de quais arquivos JAR.

java -verbose:class <other args>

Quando seu programa é executado, a JVM deve despejar para obter informações padronizadas, como:

...

[Junit.framework.Assert carregado do arquivo: / C: /Program%20Files/junit3.8.2/junit.jar]

...

matt b
fonte
3
+1 Brilhante! Resolvi um pequeno problema desagradável usando esse método, obrigado. Essa é uma excelente maneira de descobrir quando as classes se infiltram em um caminho de classe de alguma forma.
Duncan Jones
1
+1 Você salvou meu dia! Era apenas uma biblioteca que incluía classes antigas com o mesmo nome em suas fontes.
Andrii Nemchenko 08/08/19
12

Isso geralmente é causado ao usar um sistema de compilação como o Apache Ant que apenas compila arquivos java quando o arquivo java é mais recente que o arquivo de classe. Se uma assinatura de método for alterada e as classes estiverem usando a versão antiga, as coisas poderão não ser compiladas corretamente. A correção habitual é fazer uma reconstrução completa (geralmente "limpeza de formigas" e depois "formigas").

Às vezes, isso também pode ser causado durante a compilação em uma versão de uma biblioteca, mas em execução em uma versão diferente.

John Meagher
fonte
1
Na verdade, isso parece mais um problema que surge para programadores Java que usam qualquer estrutura de desenvolvimento Java: Maven, NetBeans e Apache Ant, como você pode ver em todas as respostas aqui.
HoldOffHunger
8

Se você estiver usando o Maven ou outra estrutura, e você receber esse erro quase aleatoriamente, tente uma instalação limpa como ...

clean install

Isso provavelmente funcionará se você escreveu o objeto e sabe que ele possui o método. Trabalhou para mim.

HoldOffHunger
fonte
Este também é o caso das compilações Gradle.
Jonathan Landrum
4

Isso também pode ser o resultado do uso da reflexão. Se você possui um código que reflete em uma classe e extrai um método por nome (por exemplo: with Class.getDeclaredMethod("someMethodName", .....)), sempre que o nome do método for alterado, como durante um refator, será necessário lembrar de atualizar os parâmetros para o método de reflexão para corresponder ao nova assinatura de método, ou a getDeclaredMethodchamada lançará a NoSuchMethodException.

Se esse for o motivo, o rastreamento da pilha deve mostrar o ponto em que o método de reflexão é chamado, e você só precisará atualizar os parâmetros para corresponder à assinatura real do método.

Na minha experiência, isso ocorre ocasionalmente ao testar métodos / campos particulares, e ao usar uma TestUtilitiesclasse para extrair campos para verificação de teste. (Geralmente, com código herdado que não foi projetado com o teste de unidade em mente.)

rcreswick
fonte
3

Se você estiver escrevendo um aplicativo da Web, verifique se não possui versões conflitantes de um jar no diretório de biblioteca global do contêiner e também no aplicativo. Você pode não necessariamente saber qual jar está sendo usado pelo carregador de classes.

por exemplo

  • tomcat / comum / lib
  • mywebapp / WEB-INF / lib
Cheekysoft
fonte
2

Esses problemas são causados ​​pelo uso do mesmo objeto nas mesmas duas classes. Objetos usados ​​não contém novo método foi adicionado que a nova classe de objeto contém.

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$ 

Esses problemas são causados ​​pela classe similar 02 concomitante (1 no src, 1 no arquivo jar aqui é gateway.jar)

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

Isso significa que o respectivo método não está presente na classe:

  1. Se você estiver usando jar, descompile e verifique se a versão respectiva do jar tem a classe adequada.
  2. Verifique se você compilou a classe adequada a partir da sua fonte.
Shrikant
fonte
2

Para mim, isso aconteceu porque alterei o tipo de argumento na função, de Objeto a para String a. Eu poderia resolvê-lo com limpo e construir novamente

Tito
fonte
2

Acabei de solucionar esse erro reiniciando o Eclipse e executando o aplicativo. O motivo do meu caso pode ser porque substituo meus arquivos de origem sem fechar meu projeto ou o Eclipse. O que causou uma versão diferente das classes que eu estava usando.

Ryan Luo Xu
fonte
2

Tente desta maneira: remova todos os arquivos .class nos diretórios do seu projeto (e, é claro, todos os subdiretórios). Reconstruir.

Às vezes mvn clean(se você estiver usando o maven) não limpa os arquivos .class criados manualmente por javac. E esses arquivos antigos contêm assinaturas antigas, levando a NoSuchMethodError.

WHOIF
fonte
2

Apenas adicionando às respostas existentes. Eu estava enfrentando esse problema com o tomcat no eclipse. Eu mudei uma classe e segui as etapas,

  1. Limpou e construiu o projeto em eclpise

  2. instalação limpa do mvn

  3. Tomcat reiniciado

Ainda estava enfrentando o mesmo erro. Em seguida , limpei o tomcat, limpei o diretório de trabalho do tomcat e reiniciei o servidor, e meu problema desapareceu. Espero que isso ajude alguém

Code_Mode
fonte
1

Para responder à pergunta original. De acordo com o java docs aqui :

"NoSuchMethodError" Lançado se um aplicativo tentar chamar um método especificado de uma classe (estática ou instância) e essa classe não tiver mais uma definição desse método.

Normalmente, esse erro é detectado pelo compilador; esse erro pode ocorrer apenas em tempo de execução se a definição de uma classe tiver sido alterada incompativelmente.

  1. Se isso ocorrer no tempo de execução, verifique se a classe que contém o método está no caminho da classe.
  2. Verifique se você adicionou uma nova versão do JAR e se o método é compatível.
Alcances
fonte
1

Corrigi esse problema no Eclipse renomeando um arquivo de teste do Junit.
No meu espaço de trabalho do Eclipse, tenho um projeto App e um projeto Test.
O projeto Teste tem o projeto App como um projeto necessário no caminho da construção.

Começou a obter o NoSuchMethodError.
Então percebi que a classe no projeto Teste tinha o mesmo nome que a classe no projeto App.

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

Depois de renomear o teste com o nome correto "ProjectionTest.java", a exceção desapareceu.

Dave Inlow
fonte
Eu tive uma questão semelhante. Eu tinha uma classe de dependência com o mesmo nome canônico completo. Depois de renomear a exceção foi embora.
MoralejaSinCuentoNiProverbio
1

Eu tive o mesmo erro:

  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 resolvê-lo, verifiquei, primeiro, o Diagrama de Dependência do Módulo ( click in your POM the combination -> Ctrl+Alt+Shift+Uou right click in your POM -> Maven -> Show dependencies) para entender onde exatamente havia o conflito entre as bibliotecas (Intelij IDEA). No meu caso particular, eu tinha versões diferentes das dependências de Jackson.

insira a descrição da imagem aqui insira a descrição da imagem aqui

1) Então, adicionei diretamente no meu POM do projeto explicitamente a versão mais alta - 2.8.7 desses dois.

Nas propriedades:

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

E como dependência:

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

2) Mas também pode ser resolvido usando Exclusões de Dependência .

Pelo mesmo princípio que abaixo no exemplo:

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

A dependência com a versão indesejada será excluída do seu projeto.

invzbl3
fonte
1

No meu caso, eu tinha um projeto com vários módulos e o cenário era como com.xyz.TestClassestava no módulo Ae assim como no módulo Be o módulo Adependia do módulo B. Então, ao criar um jar de montagem, acho que apenas uma versão da classe foi mantida se esse não tiver o método invocado, então eu estava obtendoNoSuchMethodError exceção de tempo de execução, mas a compilação estava correta.

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

Gaurav Khare
fonte
0

Encontrei um problema semelhante ao alterar assinaturas de método no meu aplicativo. A limpeza e reconstrução do meu projeto resolveu o "NoSuchMethodError".

cavaleiro
fonte
0

A resposta acima explica muito bem .. apenas para adicionar uma coisa Se você estiver usando o eclipse, use ctrl + shift + T e insira a estrutura de pacotes da classe (por exemplo: gateway.smpp.PDUEventListener), você encontrará todos os jars / projetos onde está presente . Remova os jarros desnecessários do caminho de classe ou adicione acima no caminho da classe. Agora ele pegará o correto.

Principe
fonte
0

Eu tive um problema semelhante.

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

Finalmente, identifiquei que a causa raiz estava mudando o tipo de dados da variável.

  1. Employee.java-> Contém a variável ( EmpId) cujo Tipo de Dados foi alterado de intpara String.
  2. ReportGeneration.java-> Recupera o valor usando o getter getEmpId(),.

Devemos reorganizar o jar incluindo apenas as classes modificadas. Como não houve alteração, ReportGeneration.javaeu estava apenas incluindo o Employee.classarquivo Jar. Eu tive que incluir o ReportGeneration.classarquivo no frasco para resolver o problema.

AnonymousCoder
fonte
0

Eu tive o mesmo problema. Isso também é causado quando há uma ambiguidade nas classes. Meu programa estava tentando chamar um método que estava presente em dois arquivos JAR presentes no mesmo caminho de local / classe. Exclua um arquivo JAR ou execute seu código para que apenas um arquivo JAR seja usado. Verifique se você não está usando o mesmo JAR ou versões diferentes do mesmo JAR que contêm a mesma classe.

DISP_E_EXCEPTION [etapa] [] [Exceção Java Z-JAVA-105 java.lang.NoSuchMethodError (com.example.yourmethod)]

ShankarDaruga
fonte
0

Na maioria das vezes, o java.lang.NoSuchMethodError é capturado no compilador, mas às vezes pode ocorrer em tempo de execução. Se esse erro ocorrer no tempo de execução, o único motivo pode ser a alteração na estrutura da classe que o tornou incompatível.

Melhor explicação: https://www.journaldev.com/14538/java-lang-nosuchmethoderror

Yash P Shah
fonte
0

Também encontrei este erro.

Meu problema era que alterei a assinatura de um método, algo como

void invest(Currency money){...}

para dentro

void invest(Euro money){...}

Este método foi chamado de um contexto semelhante ao

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

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

O compilador ficou em silêncio em relação a avisos / erros, pois o capital é tanto moeda quanto euro.

O problema apareceu devido ao fato de eu compilar apenas a classe na qual o método foi definido - Bank, mas não a classe da qual o método está sendo chamado, que contém o método main ().

Esse problema não é algo que você pode encontrar com muita frequência, pois na maioria das vezes o projeto é reconstruído manualmente ou uma ação de compilação é acionada automaticamente, em vez de apenas compilar a classe modificada.

Meu caso de usuário foi que eu gerei um arquivo .jar que deveria ser usado como um hotfix, que não continha o App.class, pois isso não foi modificado. Fazia sentido não incluí-lo, pois mantinha a classe base do argumento inicial através da herança.

O problema é que, quando você compila uma classe, o bytecode resultante é meio estático , em outras palavras, é um referência rígida .

O bytecode desmontado original (gerado com a ferramenta javap) fica assim:

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

Depois que o ClassLoader carrega o novo Bank.class compilado, ele não encontra esse método, parece que ele foi removido e não foi alterado, portanto, o erro nomeado.

Espero que isto ajude.

Mihai Savin
fonte
0

O problema no meu caso era ter duas versões da mesma biblioteca no caminho da compilação. A versão mais antiga da biblioteca não tinha a função, e a mais recente.

KK
fonte
0

Eu tive um problema semelhante com meu projeto Gradle usando Intelij. Eu o resolvi excluindo o pacote .gradle (veja a captura de tela abaixo) e reconstruindo o projeto. Pacote .gradle

J.Orlando
fonte
0

NoSuchMethodError: Passei algumas horas corrigindo esse problema, finalmente o corrigi apenas renomeando o nome do pacote, limpo e compilado ... Tente a compilação limpa primeiro, se não funcionar, tente renomear o nome da classe ou o nome do pacote e a compilação limpa. . deve ser corrigido. Boa sorte.

Shirish Singh
fonte
-2

Se o nome do seu arquivo for diferente do nome da classe que contém o método principal, é possível que esse erro possa causar.

Amit Walke
fonte