ClassNotFoundException et NoClassDefFoundError

1. Introduction

Les deux ClassNotFoundException et NoClassDefFoundError se produisent lorsque la machine virtuelle Java ne peut pas trouver une classe demandée sur le chemin de classe. Bien qu'ils semblent familiers, il existe des différences fondamentales entre les deux.

Dans ce didacticiel, nous discuterons de certaines des raisons de leurs occurrences et de leurs solutions.

2. ClassNotFoundException

ClassNotFoundException est une exception vérifiée qui se produit lorsqu'une application tente de charger une classe via son nom complet et ne trouve pas sa définition sur le chemin de classe.

Cela se produit principalement lorsque vous essayez de charger des classes à l'aide de Class.forName () , ClassLoader.loadClass () ou ClassLoader.findSystemClass () . Par conséquent, nous devons faire très attention à java.lang.ClassNotFoundException tout en travaillant avec la réflexion.

Par exemple, essayons de charger la classe de pilote JDBC sans ajouter les dépendances nécessaires qui nous obtiendront ClassNotFoundException:

@Test(expected = ClassNotFoundException.class) public void givenNoDrivers_whenLoadDriverClass_thenClassNotFoundException() throws ClassNotFoundException { Class.forName("oracle.jdbc.driver.OracleDriver"); }

3. NoClassDefFoundError

NoClassDefFoundError est une erreur fatale. Cela se produit lorsque JVM ne peut pas trouver la définition de la classe en essayant de:

  • Instancier une classe à l'aide du nouveau mot-clé
  • Charger une classe avec un appel de méthode

L'erreur se produit lorsqu'un compilateur a réussi à compiler la classe, mais que l'environnement d'exécution Java n'a pas pu localiser le fichier de classe. Cela se produit généralement lorsqu'il y a une exception lors de l'exécution d'un bloc statique ou de l'initialisation des champs statiques de la classe, de sorte que l'initialisation de la classe échoue.

Considérons un scénario qui est un moyen simple de reproduire le problème. L' initialisation de ClassWithInitErrors lève une exception. Ainsi, lorsque nous essayons de créer un objet de ClassWithInitErrors, cela lève ExceptionInInitializerError.

Si nous essayons de charger à nouveau la même classe, nous obtenons le NoClassDefFoundError:

public class ClassWithInitErrors { static int data = 1 / 0; }
public class NoClassDefFoundErrorExample { public ClassWithInitErrors getClassWithInitErrors() { ClassWithInitErrors test; try { test = new ClassWithInitErrors(); } catch (Throwable t) { System.out.println(t); } test = new ClassWithInitErrors(); return test; } }

Écrivons un cas de test pour ce scénario:

@Test(expected = NoClassDefFoundError.class) public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() { NoClassDefFoundErrorExample sample = new NoClassDefFoundErrorExample(); sample.getClassWithInitErrors(); }

4. Résolution

Parfois, diagnostiquer et résoudre ces deux problèmes peut prendre beaucoup de temps. La principale raison de ces deux problèmes est l'indisponibilité du fichier de classe (dans le chemin de classe) au moment de l'exécution.

Jetons un coup d'œil à quelques approches que nous pouvons envisager lorsque nous traitons l'un de ces éléments:

  1. Nous devons nous assurer que la classe ou le fichier jar contenant cette classe est disponible dans le chemin de classe. Sinon, nous devons l'ajouter
  2. S'il est disponible sur le chemin de classe de l'application, alors le chemin de classe est probablement remplacé. Pour résoudre ce problème, nous devons trouver le chemin de classe exact utilisé par notre application
  3. En outre, si une application utilise plusieurs chargeurs de classe, les classes chargées par un chargeur de classe peuvent ne pas être disponibles par d'autres chargeurs de classe. Pour bien le dépanner, il est essentiel de savoir comment les chargeurs de classe fonctionnent en Java

5. Résumé

Bien que ces deux exceptions soient liées au chemin de classe et à l'exécution Java incapable de trouver une classe au moment de l'exécution, il est important de noter leurs différences.

Java runtime lève ClassNotFoundException lors de la tentative de chargement d'une classe au moment de l'exécution uniquement et le nom a été fourni pendant l'exécution. Dans le cas de NoClassDefFoundError, la classe était présente au moment de la compilation, mais l'exécution Java n'a pas pu la trouver dans le chemin de classe Java pendant l'exécution.

Comme toujours, le code complet de tous les exemples est disponible à l'adresse over sur GitHub.