Qual é a diferença entre NoClassDefFoundError
e ClassNotFoundException
?
O que faz com que eles sejam jogados? Como eles podem ser resolvidos?
Costumo encontrar esses lançáveis ao modificar o código existente para incluir novos arquivos jar. Eu os atingi no lado do cliente e no servidor para um aplicativo java distribuído através do webstart.
Possíveis razões que me deparei:
- pacotes não incluídos no
build.xml
lado do cliente do código - caminho de classe de tempo de execução ausente para os novos frascos que estamos usando
- versão entra em conflito com o jar anterior
Quando os encontro hoje, adotei uma abordagem de rastreamento e erro para fazer as coisas funcionarem. Eu preciso de mais clareza e compreensão.
-verbose
(por exemplo-verbose:class -verbose:jni
) ajuda - mas os relatórios mogsie abaixo sua resposta que este não fornece nenhuma informação útil adicional :(Respostas:
A diferença das especificações da API Java é a seguinte.
Para
ClassNotFoundException
:Para
NoClassDefFoundError
:Portanto, parece que isso
NoClassDefFoundError
ocorre quando a fonte foi compilada com êxito, mas em tempo de execução, osclass
arquivos necessários não foram encontrados. Isso pode ser algo que pode acontecer na distribuição ou produção de arquivos JAR, onde nem todos osclass
arquivos necessários foram incluídos.Quanto a
ClassNotFoundException
, parece que isso pode resultar da tentativa de fazer chamadas reflexivas para as classes em tempo de execução, mas as classes que o programa está tentando chamar não existem.A diferença entre os dois é que um é um
Error
e o outro é umException
. WithNoClassDefFoundError
é umError
e surge da Java Virtual Machine com problemas para encontrar uma classe que esperava encontrar. Um programa que se espera que funcione em tempo de compilação não pode ser executado devido àclass
falta de arquivos encontrados ou não é o mesmo que foi produzido ou encontrado em tempo de compilação. Este é um erro bastante crítico, pois o programa não pode ser iniciado pela JVM.Por outro lado, o
ClassNotFoundException
é umException
, então é algo esperado e é algo que é recuperável. O uso da reflexão pode estar sujeito a erros (pois há algumas expectativas de que as coisas não saem conforme o esperado. Não há verificação em tempo de compilação para verificar se todas as classes necessárias existem, portanto, quaisquer problemas em encontrar as classes desejadas aparecerão em tempo de execução .fonte
NoClassDefFoundError
geralmente ocorre quando há um problema (exceção lançada) com o bloco estático ou a inicialização de campos estáticos da classe, portanto, a classe não pode ser inicializada com êxito.Error
e o outro é umException
. :)Uma ClassNotFoundException é lançada quando a classe relatada não é encontrada pelo ClassLoader. Isso normalmente significa que a classe está ausente no CLASSPATH. Também pode significar que a classe em questão está tentando ser carregada de outra classe que foi carregada em um carregador de classes pai e, portanto, a classe do carregador de classes filho não está visível. Às vezes, esse é o caso ao trabalhar em ambientes mais complexos, como um App Server (o WebSphere é famoso por esses problemas no carregador de classes).
Muitas vezes as pessoas tendem a confundir
java.lang.NoClassDefFoundError
comjava.lang.ClassNotFoundException
no entanto há uma distinção importante. Por exemplo, uma exceção (um erro realmente desde quejava.lang.NoClassDefFoundError
é uma subclasse de java.lang.Error) comonão significa que a classe ActiveMQConnectionFactory não esteja na CLASSPATH. De fato, é exatamente o contrário. Isso significa que a classe ActiveMQConnectionFactory foi encontrada pelo ClassLoader; no entanto, ao tentar carregar a classe, ocorreu um erro ao ler a definição da classe. Isso normalmente acontece quando a classe em questão possui blocos ou membros estáticos que usam uma classe que não é encontrada pelo ClassLoader. Portanto, para encontrar o culpado, visualize a fonte da classe em questão (ActiveMQConnectionFactory neste caso) e procure o código usando blocos ou membros estáticos. Se você não tiver acesso à fonte, simplesmente descompile-a usando o JAD.
Ao examinar o código, digamos que você encontre uma linha de código como a seguir, verifique se a classe SomeClass está no seu CLASSPATH.
Dica: Para descobrir a qual jar pertence uma classe, você pode usar o site jarFinder. Isso permite que você especifique um nome de classe usando curingas e ele procura a classe em seu banco de dados de jars. O jarhoo permite que você faça a mesma coisa, mas não é mais gratuito.
Se você deseja localizar o jar a que uma classe pertence em um caminho local, você pode usar um utilitário como o jarscan ( http://www.inetfeedback.com/jarscan/ ). Você acabou de especificar a classe que deseja localizar e o caminho do diretório raiz onde deseja iniciar a pesquisa da classe em jars e arquivos zip.
fonte
NoClassDefFoundError
é um erro de ligação basicamente. Ocorre quando você tenta instanciar um objeto (estaticamente com "novo") e não é encontrado quando estava durante a compilação.ClassNotFoundException
é mais geral e é uma exceção de tempo de execução quando você tenta usar uma classe que não existe. Por exemplo, você tem um parâmetro em uma função que aceita uma interface e alguém passa em uma classe que implementa essa interface, mas você não tem acesso à classe. Também abrange casos de carregamento de classe dinâmica, como usarloadClass()
orClass.forName()
.fonte
Um NoClassDefFoundError (NCDFE) acontece quando seu código executa "novo Y ()" e não consegue encontrar a classe Y.
Pode ser que Y esteja ausente do seu carregador de classes, como os outros comentários sugerem, mas pode ser que a classe Y não esteja assinada ou tenha uma assinatura inválida, ou que Y esteja carregado por um carregador de classe diferente, não visível para o seu código , ou mesmo que Y dependa de Z, que não pôde ser carregado por qualquer um dos motivos acima.
Se isso acontecer, a JVM lembrará o resultado do carregamento do X (NCDFE) e lançará um novo NCDFE toda vez que você solicitar Y sem informar o motivo:
salve isso como a.java em algum lugar
O código simplesmente tenta instanciar uma nova classe "b" duas vezes, além disso, não possui bugs e não faz nada.
Compile o código com
javac a.java
, Em seguida, execute a invocandojava -cp . a
- ele deve apenas imprimir duas linhas de texto e deve funcionar bem sem erros.Em seguida, exclua o arquivo "a $ b.class" (ou preencha-o com lixo ou copie a.class sobre ele) para simular a classe ausente ou corrompida. Aqui está o que acontece:
A primeira chamada resulta em uma ClassNotFoundException (lançada pelo carregador de classes quando não consegue encontrar a classe), que deve ser agrupada em um NoClassDefFoundError desmarcado, pois o código em questão (
new b()
) deve funcionar.Obviamente, a segunda tentativa também falhará, mas como você pode ver, a exceção agrupada não existe mais, porque o ClassLoader parece lembrar os carregadores de classes com falha. Você vê apenas o NCDFE com absolutamente nenhuma pista do que realmente aconteceu.
Portanto, se você vir um NCDFE sem causa raiz, precisará verificar se consegue rastrear desde a primeira vez em que a classe foi carregada para encontrar a causa do erro.
fonte
-verbose
alguma opção semelhante, dependendo da JVM específica? Provavelmente-verbose:class
, talvez-verbose:class:jni
se estiver usando JNI, mas não tenho certeza sobre a sintaxe. Se isso for útil, talvez você possa mostrar os resultados.-verbose:class
nem-verbose:jni
dar qualquer saída adicionais relevantes para a classe faltando.-verbose:class:jni
está errado: é preciso especificar duas opções distintas:-verbose:class -verbose:jni
.)De http://www.javaroots.com/2013/02/classnotfoundexception-vs.html :
ClassNotFoundException
: ocorre quando o carregador de classes não conseguiu encontrar a classe necessária no caminho da classe. Portanto, basicamente você deve verificar o caminho da classe e adicionar a classe no caminho da classe.NoClassDefFoundError
: isso é mais difícil de depurar e encontre o motivo. Isso é acionado quando, em tempo de compilação, as classes necessárias estão presentes, mas, em tempo de execução, as classes são alteradas ou removidas ou as inicializações estáticas da classe lançam exceções. Isso significa que a classe que está sendo carregada está presente no caminho de classe, mas uma das classes exigidas por essa classe é removida ou falha ao carregar pelo compilador. Então você deve ver as classes que são dependentes dessa classe.Exemplo :
Agora, depois de compilar as duas classes, se você excluir o arquivo Test1.class e executar a classe Test, ele lançará
ClassNotFoundException
: lançado quando um aplicativo tenta carregar uma classe por meio de seu nome, mas nenhuma definição para a classe com o nome especificado foi encontrada.NoClassDefFoundError
: lançado se a Java Virtual Machine tentar carregar na definição de uma classe e nenhuma definição da classe puder ser encontrada.fonte
-verbose
alguma opção semelhante, dependendo da JVM específica? Provavelmente-verbose:class
, talvez-verbose:class:jni
se estiver usando JNI, mas não tenho certeza sobre a sintaxe.-verbose:class:jni
é errado, mas você pode passar duas opções distintas:-verbose:class -verbose:jni
.Eles estão intimamente relacionados. A
ClassNotFoundException
é acionada quando o Java procura uma classe específica por nome e não pode carregá-la com êxito. ANoClassDefFoundError
é lançada quando o Java procura uma classe que esteja vinculada a algum código existente, mas não a encontrou por um motivo ou outro (por exemplo, caminho de classe errado, versão incorreta do Java, versão incorreta de uma biblioteca) e é completamente fatal pois indica que algo deu errado.Se você possui um background C, um CNFE é como uma falha no
dlopen()
/dlsym()
e um NCDFE é um problema com o vinculador; no segundo caso, os arquivos de classe em questão nunca deveriam ter sido realmente compilados na configuração que você está tentando usá-los.fonte
Exemplo 1:
Se
com/example/Class1
não existir em nenhum dos caminhos de classe, será lançadoClassNotFoundException
.Exemplo 2:
Se
com/example/Class2
existia durante a compilação de B, mas não foi encontrado durante a execução, é lançadoNoClassDefFoundError
.Ambos são exceções de tempo de execução.
fonte
ClassNotFoundException é lançado quando há uma tentativa de carregar a classe fazendo referência a ela por meio de uma String. Por exemplo, o parâmetro em Class.forName () é uma String e isso aumenta o potencial de nomes binários inválidos sendo passados para o carregador de classes.
A ClassNotFoundException é lançada quando um nome binário potencialmente inválido é encontrado; por exemplo, se o nome da classe tiver o caractere '/', você receberá uma ClassNotFoundException. Também é lançada quando a classe referenciada diretamente não está disponível no caminho de classe.
Por outro lado, NoClassDefFoundError é lançado
Em resumo, um NoClassDefFoundError geralmente é lançado em instruções new () ou invocações de métodos que carregam uma classe anteriormente ausente (em oposição ao carregamento de classes baseado em string para ClassNotFoundException), quando o carregador de classe não consegue encontrar ou carregar a definição de classe ( s)
Eventualmente, cabe à implementação do ClassLoader lançar uma instância de ClassNotFoundException quando não é possível carregar uma classe. A maioria das implementações personalizadas do carregador de classes realiza isso porque elas estendem o URLClassLoader. Geralmente, os carregadores de classes não lançam explicitamente um NoClassDefFoundError em nenhuma das implementações de métodos - essa exceção geralmente é lançada da JVM no compilador HotSpot e não pelo próprio carregador de classes.
fonte
Diferença entre ClassNotFoundException Vs NoClassDefFoundError
fonte
Exceção: Exceções ocorrem durante a execução do programa. Um programador pode lidar com essas exceções tentando o bloco catch. Temos dois tipos de exceções. Exceção marcada que lança em tempo de compilação. Exceções de tempo de execução lançadas em tempo de execução, essas exceções geralmente ocorrem devido a uma programação incorreta.
Erro: Estas não são exceções, está além do escopo do programador. Esses erros geralmente são gerados pela JVM.
fonte da imagem
Diferença:
ClassNotFoundException:
ClassNotFoundException
.ClassNotFoundException
é uma exceção verificada derivada diretamente dajava.lang.Exception
classe e você precisa fornecer tratamento explícito para elaClassNotFoundException
surge quando há um carregamento explícito da classe, fornecendo o nome da classe em tempo de execução usando ClassLoader.loadClass (), Class.forName () e ClassLoader.findSystemClass ().NoClassDefFoundError:
NoClassDefFoundError
.NoClassDefFoundError
é um erro derivado daLinkageError
classe, usado para indicar casos de erro, nos quais uma classe depende de alguma outra classe e essa classe foi alterada incompativelmente após a compilação.NoClassDefFoundError
é o resultado do carregamento implícito da classe devido a uma chamada de método dessa classe ou a qualquer acesso variável.Semelhanças:
NoClassDefFoundError
eClassNotFoundException
estão relacionados à indisponibilidade de uma classe em tempo de execução.ClassNotFoundException
eNoClassDefFoundError
estão relacionados ao caminho de classe Java.fonte
Dadas as ações básicas do carregador de classes:
Este é um artigo que me ajudou muito a entender a diferença: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html
Portanto, um ClassNotFoundException é uma causa raiz de NoClassDefFoundError .
E um NoClassDefFoundError é um caso especial de erro de carregamento de tipo, que ocorre na etapa Vinculação .
fonte
Adicione um possível motivo na prática:
Na prática, o erro pode ser gerado silenciosamente , por exemplo, você envia uma tarefa de timer e na tarefa de timer lança Error , enquanto na maioria dos casos, seu programa apenas captura Exception . Em seguida, o loop principal do timer termina sem nenhuma informação. Um erro semelhante ao NoClassDefFoundError é ExceptionInInitializerError , quando o inicializador estático ou o inicializador de uma variável estática lança uma exceção.
fonte
ClassNotFoundException é uma exceção verificada que ocorre quando dizemos à JVM para carregar uma classe por seu nome de string usando os métodos Class.forName () ou ClassLoader.findSystemClass () ou ClassLoader.loadClass () e a classe mencionada não é encontrada no caminho de classe.
Na maioria das vezes, essa exceção ocorre quando você tenta executar um aplicativo sem atualizar o caminho de classe com os arquivos JAR necessários. Por exemplo, você pode ter visto essa exceção ao executar o código JDBC para conectar-se ao seu banco de dados, ieMySQL, mas seu caminho de classe não possui JAR para ele.
O erro NoClassDefFoundError ocorre quando a JVM tenta carregar uma classe específica que faz parte da execução do seu código (como parte de uma chamada de método normal ou como parte da criação de uma instância usando a nova palavra-chave) e essa classe não está presente no seu caminho de classe, mas estava presente no momento da compilação porque, para executar seu programa, você precisa compilá-lo e, se estiver tentando usar uma classe que não esteja presente, o compilador gerará um erro de compilação.
Abaixo está a breve descrição
Você pode ler Tudo sobre ClassNotFoundException Vs NoClassDefFoundError para obter mais detalhes.
fonte
Lembro-me o seguinte repetidamente quando preciso atualizar
ClassNotFoundException
Hierarquia de Classes
Durante a depuração
NoClassDefFoundError
Hierarquia de Classes
Durante a depuração
fonte
ClassNotFoundException e NoClassDefFoundError ocorrem quando uma classe específica não é encontrada no tempo de execução. No entanto, elas ocorrem em diferentes cenários.
ClassNotFoundException é uma exceção que ocorre quando você tenta carregar uma classe em tempo de execução usando os métodos Class.forName () ou loadClass () e as classes mencionadas não são encontradas no caminho de classe.
NoClassDefFoundError é um erro que ocorre quando uma classe específica está presente no tempo de compilação, mas estava ausente no tempo de execução.
Quando você compila o programa acima, dois arquivos .class serão gerados. Um é A.class e outro é B.class. Se você remover o arquivo A.class e executar o arquivo B.class, o Java Runtime System exibirá NoClassDefFoundError como abaixo:
fonte