ClassNotFoundException vs NoClassDefFoundError

ClassNotFoundException vs NoClassDefFoundError

1. Einführung

SowohlClassNotFoundException als auchNoClassDefFoundError treten auf, wenn die JVM eine angeforderte Klasse im Klassenpfad nicht finden kann. Obwohl sie vertraut aussehen, gibt es einige Kernunterschiede zwischen diesen beiden.

In diesem Tutorial werden wir einige der Gründe für ihr Auftreten und ihre Lösungen diskutieren.

2. ClassNotFoundException

ClassNotFoundException ist eine geprüfte Ausnahme, die auftritt, wenn eine Anwendung versucht, eine Klasse über ihren vollständig qualifizierten Namen zu laden, und ihre Definition im Klassenpfad nicht finden kann.

Dies tritt hauptsächlich auf, wenn versucht wird, Klassen mitClass.forName(),ClassLoader.loadClass() oderClassLoader.findSystemClass() zu laden. Daher müssen wir bei der Arbeit mit Reflexion besonders aufjava.lang.ClassNotFoundException achten.

Versuchen wir beispielsweise, die JDBC-Treiberklasse zu laden, ohne die erforderlichen Abhängigkeiten hinzuzufügen, die unsClassNotFoundException: bringen

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

3. NoClassDefFoundError

NoClassDefFoundError ist ein schwerwiegender Fehler. Es tritt auf, wenn JVM die Definition der Klasse nicht finden kann, während versucht wird:

  • Instanziieren Sie eine Klasse mit dem Schlüsselwortnew

  • Laden Sie eine Klasse mit einem Methodenaufruf

Der Fehler tritt auf, wenn ein Compiler die Klasse erfolgreich kompilieren konnte, Java Runtime die Klassendatei jedoch nicht finden konnte. In der Regel tritt eine Ausnahme auf, wenn ein statischer Block ausgeführt oder statische Felder der Klasse initialisiert werden und die Klasseninitialisierung fehlschlägt.

Betrachten wir ein Szenario, das eine einfache Möglichkeit darstellt, das Problem zu reproduzieren. Die Initialisierung vonClassWithInitErrorslöst eine Ausnahme aus. Wenn wir also versuchen, ein Objekt mitClassWithInitErrors, zu erstellen, wirdExceptionInInitializerError. ausgelöst

Wenn wir versuchen, dieselbe Klasse erneut zu laden, erhalten wirNoClassDefFoundError:

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;
    }
}

Schreiben wir einen Testfall für dieses Szenario:

@Test(expected = NoClassDefFoundError.class)
public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() {

    NoClassDefFoundErrorExample sample
     = new NoClassDefFoundErrorExample();
    sample.getClassWithInitErrors();
}

4. Auflösung

Manchmal kann es sehr zeitaufwendig sein, diese beiden Probleme zu diagnostizieren und zu beheben. Der Hauptgrund für beide Probleme ist die Nichtverfügbarkeit der Klassendatei (im Klassenpfad) zur Laufzeit.

Schauen wir uns einige Ansätze an, die wir in Betracht ziehen können, wenn wir uns mit einem dieser beiden befassen:

  1. Wir müssen sicherstellen, dass die Klasse oder die JAR-Datei, die diese Klasse enthält, im Klassenpfad verfügbar ist. Wenn nicht, müssen wir es hinzufügen

  2. Wenn es im Klassenpfad der Anwendung verfügbar ist, wird der Klassenpfad höchstwahrscheinlich überschrieben. Um dies zu beheben, müssen wir den genauen Klassenpfad ermitteln, der von unserer Anwendung verwendet wird

  3. Wenn eine Anwendung mehrere Klassenladeprogramme verwendet, stehen Klassen, die von einem Klassenladeprogramm geladen wurden, möglicherweise nicht für andere Klassenladeprogramme zur Verfügung. Zur Fehlerbehebung ist es wichtig,how classloaders work in Java zu kennen

5. Zusammenfassung

Diese beiden Ausnahmen beziehen sich auf Klassenpfad und Java-Laufzeit, die zur Laufzeit keine Klasse finden können. Es ist jedoch wichtig, ihre Unterschiede zu beachten.

Die Java-Laufzeit löstClassNotFoundException aus, während versucht wird, eine Klasse nur zur Laufzeit zu laden, und der Name wurde zur Laufzeit angegeben. Im Fall vonNoClassDefFoundError, thewar die Klasse zur Kompilierungszeit vorhanden, aber die Java-Laufzeit konnte sie zur Laufzeit nicht im Java-Klassenpfad finden.

Wie immer finden Sie den vollständigen Code für alle Beispiele inover on GitHub.