ClassNotFoundException vs NoClassDefFoundError

ClassNotFoundException vs NoClassDefFoundError

1. introduction

LesClassNotFoundException etNoClassDefFoundError 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 quelques différences fondamentales entre ces deux.

Dans ce didacticiel, nous allons discuter 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 en utilisantClass.forName(),ClassLoader.loadClass() ouClassLoader.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 permettront d'obtenirClassNotFoundException:

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

3. NoClassDefFoundError

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

  • Instanciez une classe à l'aide du mot clénew

  • Charger une classe avec un appel de méthode

L'erreur se produit lorsqu'un compilateur a pu compiler la classe avec succès, mais que Java n'a pas pu localiser le fichier de classe. Cela se produit généralement lorsqu'il existe une exception lors de l'exécution d'un bloc statique ou de l'initialisation des champs statiques de la classe. Par conséquent, l'initialisation de la classe échoue.

Prenons un scénario qui est un moyen simple de reproduire le problème. L'initialisation deClassWithInitErrors lève une exception. Ainsi, lorsque nous essayons de créer un objet deClassWithInitErrors,, il jetteExceptionInInitializerError.

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

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 scénario 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 classpath) au moment de l’exécution.

Jetons un coup d'œil à quelques approches que nous pouvons envisager pour traiter 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 classpath. Si non, nous devons l'ajouter

  2. S'il est disponible sur le chemin de classe de l'application, 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. De même, 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 connaîtrehow classloaders work in Java

5. Sommaire

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

Le runtime Java lèveClassNotFoundException 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 deNoClassDefFoundError, the, la classe était présente au moment de la compilation, mais le runtime Java n'a pas pu le trouver dans le chemin de classe Java pendant l'exécution.

Comme toujours, le code complet de tous les exemples peut être trouvéover on GitHub.