Diferença entre NoClassDefFoundError e ClassNotFoundException

Tempo de leitura: menos de 1 minuto

a-excecaoQuem (programador Java) nunca se deparou com estas exceções NoClassDefFoundError e ClassNotFoundException? Elas ocorrem com certa frequência e podem dar uma bela dor de cabeça.

Esta semana estamos homologando a nova versão do sistema no Websphere 7, e cara… que trampo hen!!

Atualmente, por algum motivo, depois que a aplicação é “deployada”, no classpath do Webphere não consta uma classe anônima do Hibernate 4.3.8 (versão que estamos usando): org.hibernate.type.descriptor.sql.DateTypeDescriptor$1. Aparentemente é algum problema na ordem do class loader, já que empacotamos o Hibernate no projeto.

Eis que aí a famigerada exceção NoClassDefFoundError é lançada, assim que um processo é executado. Sendo assim decidi escrever sobre estas exceções.

Podemos dizer que os erros significam a mesma coisa, a classe procurada não foi encontrada. No entanto, cada erro será lançado dependendo da maneira como a classe está sendo procurada.

No caso do NoClassDefFoundError, suponha que em tempo de compilação a classe está no classpath, assim nenhum erro ocorre. Já durante a execução, quando a JVM invocar um método ou uma instância de classe e a mesma não for encontrada no classpath, o erro é lançado.

Este erro pode ser provocado desta forma:

[code language=”java”]
public class TesteErro {
public static void main(String[] args) {
//referência direta para a classe ClasseQualquer
new ClasseQualquer();
}
}

class ClasseQualquer {}
[/code]

Compilando este código, o java te retornará duas class: TesteErro.class e TesteErro$ClasseQualquer.class

Quando o programa for executado, nenhum problema será notado. No entanto, se removermos a classe TesteErro$ClasseQualquer.class, e executamos o programa novamente, o erro será lançado.

A saída será algo como:

[code language=”bash”]
Exception in thread "main" java.lang.NoClassDefFoundError: ClasseQualquer
at TesteErro.main(TesteErro.java:4)
[/code]

Já a exceção ClassNotFoundException, acontece normalmente quando se usa reflexão. Se existir um código que carrega uma classe usando Class.forName() ou Class.class.getClassLoader().loadClass() e a classe não existir no classpath, o erro é lançado. Neste caso, a classe procurada, não precisa necessariamente ter sido compilada junto com a classe que à referência.

Este erro pode ser simulado desta forma:

[code language=”java”]
public class TesteErro {
public static void main(String[] args) throws Exception {
//referência indireta (qualified name) para a classe ClasseQualquer
Object o = Class.forName("esta.classe.nao.existe.ClasseQualquer").newInstance();
}
}
[/code]

A saída será algo como:

[code language=”bash”]
Exception in thread "main" java.lang.ClassNotFoundException: esta.classe.nao.existe.ClasseQualquer
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
[/code]

No exemplo a cima, a classe não precisa estar presente durante a compilação. Já na execução, a ausência da classe será percebida e a exceção é lançada.

Nenhum comentário

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *