Por que estou recebendo um NoClassDefFoundError em Java?


530

Estou recebendo um NoClassDefFoundErrorquando executo meu aplicativo Java. Qual é tipicamente a causa disso?


1
Eu acredito que isso também pode acontecer se você não executar o seu programa java com a sintaxe correta. Por exemplo, você deve chamar sua classe da pasta bin bin com o nome completo do pacote (por exemplo, my.package.myClass). Eu seria mais específico se pudesse, mas não sou muito cara de java. Só me lembro de estragar isso algumas vezes.
Hadder franco

17
@BoltClock Precisamos de uma pergunta canônica para apontar as inúmeras duplicatas. Por que não pode ser isso?
Raedwald 29/06

21
Você já pensou em mudar a resposta aceita para que a que a comunidade considere mais valiosa esteja no topo?
Martin Smith

Respostas:


264

Isso é causado quando há um arquivo de classe do qual seu código depende e está presente no tempo de compilação, mas não encontrado no tempo de execução. Procure diferenças no tempo de construção e nos caminhos de classe do tempo de execução.


1
Eu tive esse erro ao colocar um arquivo de origem no espaço para nome / pacote errado. Eu descobri que eu poderia simplesmente colocá-lo em qualquer lugar, e o compilador estava feliz. Acontece que eu deveria ter sido mais diligente para o tempo de execução ser feliz também.
CenterOrbit 21/10

1
Eu tive esse erro uma vez quando meu servidor ficou sem memória durante o upload de um arquivo. Sempre que eu tentava o upload, recebia um erro diferente. Eventualmente, ele me disse que não tinha espaço de pilha suficiente.
James M. Lay

81
Esta resposta não é necessariamente verdadeira e será enganosa para muitas pessoas! Veja a melhor resposta de Jared abaixo.
Dave L.

4
@DaveL. Obrigado! A resposta de Jared com mais de 400 upvotes está bem abaixo! Uma resposta com -4 up (down?) Votos está bem acima dela. Há algo suspeito na lógica de ordenação de respostas da SO.
Saurabh Patil

1
Essa é uma possibilidade remota para alguém, mas encontrei esse erro porque a classe em questão continha um SimpleDateFormat que foi inicializado com um caractere inválido (eu tinha T no meio em vez de 'T').
Ryan D

818

Embora seja possível que isso ocorra devido a uma incompatibilidade de caminho de classe entre o tempo de compilação e o tempo de execução, isso não é necessariamente verdade.

É importante manter duas ou três exceções diferentes em mente neste caso:

  1. java.lang.ClassNotFoundException Essa exceção indica que a classe não foi encontrada no caminho de classe. Isso indica que estávamos tentando carregar a definição de classe e a classe não existia no caminho de classe.

  2. java.lang.NoClassDefFoundError Essa exceção indica que a JVM procurou em sua estrutura de dados de definição de classe interna a definição de uma classe e não a encontrou. Isso é diferente de dizer que não foi possível carregar o caminho de classe. Normalmente, isso indica que anteriormente tentamos carregar uma classe do caminho de classe, mas ela falhou por algum motivo - agora estamos tentando usar a classe novamente (e, portanto, precisamos carregá-la, pois ela falhou da última vez), mas nós ' nem vamos tentar carregá-lo, porque falhamos ao carregá-lo mais cedo (e suspeitamos razoavelmente que falharíamos novamente). A falha anterior pode ser um ClassNotFoundException ou um ExceptionInInitializerError (indicando uma falha no bloco de inicialização estática) ou qualquer número de outros problemas. O ponto é que um NoClassDefFoundError não é necessariamente um problema de caminho de classe.


30
Obrigado por mencionar a causa de um NoClassDefFoundError, isso me ajudou muito! No meu caso, um ExceptionInInitializerError foi lançado antes, foi assim que descobri os erros nos blocos estáticos.
Thomas

@ Jared, Quando eu estiver recebendo Error: Could not find or load main class, ele será classificado em qual categoria de erro?
Vikram

@Pops: Feita a linguagem mais detalhado para especificar os objetos dos verbos "tentar" :)
Jared

1
@Vikram a "não foi possível encontrar ou carregar a classe principal" não é uma exceção Java, é causada pelo iniciador (que inspeciona o JAR e o atributo manifest principal).
Eckes

2
ClassNotFoundException também é lançado quando uma classe tem inicialização estática que gera um erro ou exceção. Eles provavelmente deveriam ter escolhido um nome diferente para esse evento.
Coladict

125

Aqui está o código para ilustrar java.lang.NoClassDefFoundError. Por favor, veja a resposta de Jared para uma explicação detalhada.

NoClassDefFoundErrorDemo.java

public class NoClassDefFoundErrorDemo {
    public static void main(String[] args) {
        try {
            // The following line would throw ExceptionInInitializerError
            SimpleCalculator calculator1 = new SimpleCalculator();
        } catch (Throwable t) {
            System.out.println(t);
        }
        // The following line would cause NoClassDefFoundError
        SimpleCalculator calculator2 = new SimpleCalculator();
    }

}

SimpleCalculator.java

public class SimpleCalculator {
    static int undefined = 1 / 0;
}

3
E o motivo é que, após a primeira tentativa, a jvm já sabe que não vai funcionar e lança exceção diferente na segunda vez?
Ikamen

@ikamen Aparentemente, ele armazenou em algum lugar a inicialização malsucedida da classe SimpleCalculatorapós a divisão por zero? Alguém tem uma referência à documentação oficial para esse comportamento?
ᴠɪɴᴄᴇɴᴛ

4
@PhilipRego Não sei ao certo o que você quer dizer com NoClassDefFoundError 'puro'. Na primeira vez que new SimpleCalculator()você chama, você obtém um ExceptionInInitializerError causado por ArithmeticException. Na segunda vez que você liga, new SimpleCalculator()você obtém um NoClassDefFoundError tão puro quanto qualquer outro. O ponto é que você pode obter um NoClassDefFoundError por um motivo diferente de SimpleCalculator.class que não esteja no caminho de classe no tempo de execução.
harperska

36

NoClassDefFoundError em Java

Definição:

  1. O Java Virtual Machine não consegue encontrar uma classe específica em tempo de execução que estava disponível no momento da compilação.

  2. Se uma classe estava presente durante o tempo de compilação, mas não estava disponível no caminho de classe java durante o tempo de execução.

insira a descrição da imagem aqui

Exemplos:

  1. A classe não está no Classpath, não existe uma maneira exata de conhecê-lo, mas muitas vezes você pode simplesmente dar uma olhada para imprimir System.getproperty ("java.classpath") e imprimirá o caminho de classe a partir daí você pode pelo menos obter uma idéia do seu caminho de classe real em tempo de execução.
  2. Um exemplo simples de NoClassDefFoundError is class pertence a um arquivo JAR ausente ou o JAR não foi adicionado ao caminho de classe ou, às vezes, o nome do jar foi alterado por alguém como no meu caso, um dos meus colegas alterou tibco.jar para tibco_v3.jar e o programa é falhando com java.lang.NoClassDefFoundError e eu queria saber o que há de errado.

  3. Apenas tente executar com a opção explicitamente -classpath com o caminho de classe que você acha que funcionará e, se estiver funcionando, é um pequeno sinal claro de que alguém está substituindo o caminho de classe java.

  4. O problema de permissão no arquivo JAR também pode causar NoClassDefFoundError em Java.
  5. Erros de digitação na configuração XML também podem causar NoClassDefFoundError em Java.
  6. quando sua classe compilada, definida em um pacote, não estiver presente no mesmo pacote durante o carregamento, como no caso de JApplet, ela lançará NoClassDefFoundError em Java.

Soluções possíveis:

  1. A classe não está disponível no Java Classpath.
  2. Se você estiver trabalhando no ambiente J2EE, a visibilidade de Class entre vários Classloader também poderá causar java.lang.NoClassDefFoundError, consulte exemplos e seção de cenário para discussão detalhada.
  3. Verifique java.lang.ExceptionInInitializerError no seu arquivo de log. NoClassDefFoundError devido à falha na inicialização estática é bastante comum.
  4. Como NoClassDefFoundError é uma subclasse de java.lang.LinkageError, ela também pode surgir se uma dependência dela, como a biblioteca nativa, não estiver disponível.
  5. Qualquer script de inicialização está substituindo a variável de ambiente Classpath.
  6. Você pode estar executando seu programa usando o comando jar e a classe não foi definida no atributo ClassPath do arquivo de manifesto.

Recursos:

3 maneiras de resolver NoClassDefFoundError

java.lang.NoClassDefFoundError Padrões de problemas


1
Ótima resposta. Acho que tentei de tudo o que você sugere e ainda tenho esse problema. Posso excluir alguns deles devido ao jar trabalhar com spring, mas parece não gostar do java.sql (no meu caso, o driver sap db para Hana).
perfil completo de JE Carter II

Na verdade, é chamado System.getproperty ("java.class.path")
RIJIK

33

Descobri que às vezes recebo um erro NoClassDefFound quando o código é compilado com uma versão incompatível da classe encontrada no tempo de execução. A instância específica que me lembro é da biblioteca de eixos apache. Na verdade, havia duas versões no meu caminho de classe em tempo de execução e ele pegava a versão desatualizada e incompatível e não a correta, causando um erro NoClassDefFound. Isso estava em um aplicativo de linha de comando em que eu estava usando um comando semelhante a este.

set classpath=%classpath%;axis.jar

Consegui fazê-lo pegar a versão correta usando:

set classpath=axis.jar;%classpath%;

4
Teve o mesmo problema. Acontece que eu compilei o arquivo war com Java7, mas minha instalação do Tomcat estava usando Java6. Eu tive que atualizar minhas variáveis ​​ambientais
duvo

4
Se isso acontecer assim, direi que o Java está uma bagunça. +2 se isso for verdade. Não foi possível verificar isso ainda. Se for considerado verdadeiro vai fazer + 1 novamente (nos comentários)
supernova

7

Esta é a melhor solução que encontrei até agora.

Suponha que tenhamos um pacote chamado org.mypackagecontendo as classes:

  • HelloWorld (classe principal)
  • SupportClass
  • UtilClass

e os arquivos que definem este pacote são armazenados fisicamente no diretório D:\myprogram(no Windows) ou /home/user/myprogram(no Linux).

A estrutura do arquivo ficará assim: insira a descrição da imagem aqui

Quando invocamos Java, que especifique o nome do aplicativo para executar: org.mypackage.HelloWorld. No entanto, também devemos informar ao Java onde procurar os arquivos e diretórios que definem nosso pacote. Então, para iniciar o programa, precisamos usar o seguinte comando: insira a descrição da imagem aqui


6

Eu estava usando o Spring Framework com o Maven e resolvi esse erro no meu projeto.

Houve um erro de tempo de execução na classe. Eu estava lendo uma propriedade como número inteiro, mas quando leu o valor do arquivo de propriedades, seu valor foi duplo.

O Spring não me deu um rastreamento completo da pilha em qual linha o tempo de execução falhou. Simplesmente disse NoClassDefFoundError. Mas quando eu o executei como um aplicativo Java nativo (removendo-o do MVC), ele forneceu ExceptionInInitializerErrorqual era a causa verdadeira e qual foi a maneira como eu rastreei o erro.

A resposta da @ xli me deu uma ideia do que pode estar errado no meu código.


1
A mesma coisa aconteceu comigo ao programar um Servlet ( NoClassDefFoundErrorna verdade, foi causado por ExceptionInInitalizerError, o que foi causado por DateTimeParseException). É um pouco enganador, não é? Eu sei que eles provavelmente tiveram suas razões para fazer dessa maneira, mas seria muito bom ter pelo menos uma pequena dica, que NoClassDefFoundErrorfoi o resultado de outra exceção, sem a necessidade de deduzi-la. Apenas jogar de ExceptionInInitializerErrornovo seria muito mais claro. Às vezes, a conexão entre os dois pode não ser tão óbvia.
Bartłomiej Zieliński

5

Recebo NoClassFoundError quando as classes carregadas pelo carregador de classes de tempo de execução não podem acessar as classes já carregadas pelo java rootloader. Como os diferentes carregadores de classes estão em domínios de segurança diferentes (de acordo com java), a jvm não permitirá que as classes já carregadas pelo rootloader sejam resolvidas no espaço de endereço do carregador de tempo de execução.

Execute seu programa com 'java -javaagent: tracer.jar [YOUR java ARGS]'

Produz saída mostrando a classe carregada e o env do carregador que carregou a classe. É muito útil rastrear por que uma classe não pode ser resolvida.

// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5

import java.lang.instrument.*;
import java.security.*;

// manifest.mf
// Premain-Class: ClassLoadTracer

// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class

// java -javaagent:tracer.jar  [...]

public class ClassLoadTracer 
{
    public static void premain(String agentArgs, Instrumentation inst) 
    {
        final java.io.PrintStream out = System.out;
        inst.addTransformer(new ClassFileTransformer() {
            public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

                String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
                out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);

                // dump stack trace of the thread loading class 
                Thread.dumpStack();

                // we just want the original .class bytes to be loaded!
                // we are not instrumenting it...
                return null;
            }
        });
    }
}

1
Link está morto. Experimente a versão arquivada: web.archive.org/web/20131216000019/https://blogs.oracle.com/…
avgvstvs

5

Um caso interessante no qual você pode ver muitos NoClassDefFoundErrorsé quando:

  1. throwum RuntimeExceptionno staticbloco da sua turmaExample
  2. Intercepte-o (ou se simplesmente não importa como se fosse lançado em um caso de teste )
  3. Tente criar uma instância desta classe Example

static class Example {
    static {
        thisThrowsRuntimeException();
    }
}

static class OuterClazz {

    OuterClazz() {
        try {
            new Example();
        } catch (Throwable ignored) { //simulating catching RuntimeException from static block
            // DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
        }

        new Example(); //this throws NoClassDefFoundError
    }
}

NoClassDefErrorserá lançado acompanhado ExceptionInInitializerErrorpelo bloco estático RuntimeException.


Este é um caso especialmente importante quando você vê NoClassDefFoundErrorsseus TESTES UNITÁRIOS .

De certa forma, você está "compartilhando" a staticexecução do bloco entre os testes, mas a inicial ExceptionInInitializerErrorserá apenas em um caso de teste. O primeiro que usa a Exampleclasse problemática . Outros casos de teste que usam a Exampleclasse serão lançados NoClassDefFoundErrors.


4
Este é um conselho bastante útil na vida real. Eu apenas tive a mesma situação com os inicializadores de atributos de classe. Você só tem uma chance de ver o problema real no log. Depois que a classe é carregada (ou tentada de qualquer maneira), você precisa reiniciar tudo.
DailyFrankPeter

4

A técnica abaixo me ajudou muitas vezes:

System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());

onde TheNoDefFoundClass é a classe que pode ser "perdida" devido a uma preferência por uma versão mais antiga da mesma biblioteca usada pelo seu programa. Isso ocorre com mais freqüência nos casos em que o software cliente está sendo implantado em um contêiner dominante, armado com seus próprios carregadores de classes e toneladas de versões antigas das bibliotecas mais populares.



1

Corrigi o meu problema desativando as preDexLibraries para todos os módulos:

dexOptions {
        preDexLibraries false
        ...

1

NoClassDefFoundErrortambém pode ocorrer quando um inicializador estático tenta carregar um pacote configurável de recursos que não está disponível em tempo de execução, por exemplo, um arquivo de propriedades que a classe afetada tenta carregar do META-INFdiretório, mas não existe. Se você não capturar NoClassDefFoundError, às vezes não poderá ver o rastreamento completo da pilha; Para superar isso, você pode usar temporariamente uma catchcláusula para Throwable:

try {
    // Statement(s) that cause the affected class to be loaded
} catch (Throwable t) {
    Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}

Isto está incorreto. Um recurso ausente não fornecerá esse erro. Você o receberá apenas se faltar uma aula .
Stephen C

@StephenC Talvez eu deva enfatizar mais essa parte, mas escrevi for example a properties file that the affected class tries to load from the META-INF directory. Isso realmente aconteceu comigo e eu pude resolver isso NoClassDefFoundErroradicionando o arquivo de propriedades que estava faltando. Eu adicionei esta resposta exatamente porque não se esperaria esse erro nas circunstâncias mencionadas.
ᴠɪɴᴄᴇɴᴛ

1
Você perdeu algo muito importante em sua explicação, porque a única maneira de um arquivo de recurso ausente poder acionar essa exceção é se você estiver tentando carregar o arquivo de recurso em uma staticinicialização ... o que acionou uma exceção não verificada e causou a classe init falhar. Qualquer exceção desmarcada propagada da inicialização estática faria isso.
Stephen C

Se eu estiver errado (isto é, não se deve a falha na staticinicialização), eu estaria interessado em ver um exemplo real (isto é, um MCVE) que demonstra o comportamento.
Stephen C

1
@StephenC Você está absolutamente certo :( Procurei o caso em que encontrei esse problema e, de fato, envolvia um inicializador estático tentando carregar um pacote de recursos. Aumentarei / corrigirei minha descrição da causa. Obrigado por apontar isso para fora.
ᴠɪɴᴄᴇɴᴛ

1

Eu recebi esse erro ao adicionar a dependência do Maven de outro módulo ao meu projeto, o problema foi finalmente resolvido com a adição -Xss2mda opção JVM do meu programa (é um megabyte por padrão desde o JDK5.0). Acredita-se que o programa não tenha pilha suficiente para carregar a classe.


0

Se alguém vier aqui por causa de java.lang.NoClassDefFoundError: org/apache/log4j/Loggererro, no meu caso, foi produzido porque usei o log4j 2 (mas não adicionei todos os arquivos que o acompanham) e alguma biblioteca de dependência utilizou o log4j 1. A solução foi adicionar o Log4j 1.x bridge: o jar log4j-1.2-api-<version>.jarque acompanha o log4j 2. Mais informações na migração do log4j 2 .


0

Duas cópias diferentes do checkout do mesmo projeto

No meu caso, o problema era a incapacidade do Eclipse de diferenciar entre duas cópias diferentes do mesmo projeto. Eu tenho um bloqueado no tronco (controle de versão SVN) e o outro trabalhando em uma ramificação por vez. Tentei uma alteração na cópia de trabalho como um caso de teste JUnit, que incluía extrair uma classe interna privada para ser uma classe pública por conta própria e enquanto ele estava funcionando, abro a outra cópia do projeto para procurar outras parte do código que precisava de alterações. Em algum momento, o grupo NoClassDefFoundErrorapareceu reclamando que a classe interna privada não estava lá; clicar duas vezes no rastreamento da pilha levou-me ao arquivo de origem na cópia incorreta do projeto.

Fechar a cópia de tronco do projeto e executar o caso de teste novamente se livrou do problema.


0

Este erro pode ser causado por requisitos de versão Java não verificados .

No meu caso, consegui resolver esse erro, ao criar um projeto de código aberto de alto perfil, alternando do Java 9 para o Java 8 usando o SDKMAN! .

sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu

Em seguida, faça uma instalação limpa, conforme descrito abaixo.


Ao usar o Maven como sua ferramenta de criação, às vezes é útil - e geralmente gratificante, fazer uma compilação limpa de 'instalação' com o teste desativado .

mvn clean install -DskipTests

Agora que tudo foi construído e instalado, você pode prosseguir e executar os testes.

mvn test


0

Também pode ser porque você copia o arquivo de código de um IDE com um determinado nome de pacote e deseja tentar executá-lo usando o terminal. Você precisará remover o nome do pacote do código primeiro. Isso acontece comigo.


0

No meu caso, eu estava recebendo esse erro devido a uma incompatibilidade nas versões do JDK. Quando tentei executar o aplicativo da Intelij, ele não estava funcionando, mas funcionou na linha de comando. Isso ocorre porque o Intelij estava tentando executá-lo com o Java 11 JDK que estava configurado, mas na linha de comando estava em execução com o Java 8 JDK. Depois de alternar essa configuração em Arquivo> Estrutura do projeto> Configurações do projeto> SDK do projeto, funcionou para mim.


0

Todo mundo fala aqui sobre algumas coisas de configuração Java, problemas de JVM etc., no meu caso, o erro não estava relacionado a esses tópicos e tinha uma razão muito trivial e fácil de resolver: eu tinha uma anotação errada no meu endpoint no meu Controller ( Aplicativo Spring Boot).


0

Eu tive um problema interessante com o NoClassDefFoundError no JavaEE, trabalhando com o servidor Liberty. Eu estava usando adaptadores de recursos IMS e meu server.xml já tinha um adaptador de recursos para imsudbJXA.rar. Quando adicionei um novo adaptador para imsudbXA.rar, eu começava a receber esse erro para objetos de instância para DLIException, IMSConnectionSpec ou SQLInteractionSpec. Não consegui entender o motivo, mas resolvi criando um novo server.xml para o meu trabalho usando apenas imsudbXA.rar. Estou certo de que o uso de vários adaptadores de recursos no server.xml é bom, mas não tive tempo de analisar isso.


-1

Java não conseguiu encontrar a classe A em tempo de execução. A Classe A estava no projeto ArtClient de um novo espaço de trabalho. Portanto, importei o ArtClient para o meu projeto Eclipse. Dois dos meus projetos estavam usando o ArtClient como dependência. Alterei a referência da biblioteca para a referência do projeto para esses (Build Path -> Configure Build Path).

E o problema foi embora.


-1

Eu tive o mesmo problema e fiquei em estoque por muitas horas.

Eu encontrei a solução. No meu caso, havia o método estático definido devido a isso. A JVM não pode criar o outro objeto dessa classe.

Por exemplo,

private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");

-6

Recebi essa mensagem depois de remover dois arquivos da biblioteca SRC e, quando os trouxe de volta, continuei vendo essa mensagem de erro.

Minha solução foi: Reinicie o Eclipse. Desde então, eu não vi essa mensagem novamente :-)


4
Isso é explicado pela resposta mais votada. Quando você compilou pela primeira vez, os arquivos estavam lá, você removeu alguns arquivos e as classes foram excluídas. Assim, em tempo de execução, você obtém o ClassNotFound e os traz de volta, mas o Eclipse ainda não observe que as classes geradas ainda estavam ausentes, mas depois que você reiniciou o Eclipse, a área de trabalho foi atualizada e as classes estavam novamente disponíveis, mas em geral isso não é uma solução ou solução alternativa, a solução está localizando qual classe / jar está ausente no tempo de execução caminho de classe.
Jose Manuel Gomez Alvarez

-7

Verifique se isso corresponde ao module:appe module:lib:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }

3
Como sua solução é relevante para esse problema comum?
Taavi Ilves

A configuração da amostra não é equilibrada (três {se dois }). Consegues consertar isso?
Peter Mortensen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.