ClassNotFoundException vs NoClassDefFoundError

1. Bemutatkozás

Mindkét ClassNotFoundException és NoClassDefFoundError akkor fordulnak elő, amikor a JVM nem talál egy kért osztályt az osztályúton. Bár ismerősnek tűnnek, van néhány alapvető különbség e kettő között.

Ebben az oktatóanyagban megvitatjuk az előfordulásuk okait és megoldásaikat.

2. ClassNotFoundException

ClassNotFoundException egy bejelölt kivétel, amely akkor fordul elő, amikor egy alkalmazás megpróbálja betölteni az osztályt a teljesen minősített nevén keresztül, és nem találja a definícióját az osztályúton.

Ez főleg akkor történik, amikor osztályokat próbálunk betölteni Class.forName (), ClassLoader.loadClass () vagy ClassLoader.findSystemClass (). Ezért fokozottan vigyáznunk kell java.lang.ClassNotFoundException miközben reflexióval dolgozik.

Például próbáljuk meg betölteni a JDBC illesztőprogram osztályt anélkül, hogy hozzáadnánk a szükséges függőségeket, amelyek megkapják ClassNotFoundException:

@Test (várható = ClassNotFoundException.class) public void givenNoDrivers_whenLoadDriverClass_thenClassNotFoundException () dobja a ClassNotFoundException {Class.forName ("oracle.jdbc.driver.OracleDriver"); }

3. NoClassDefFoundError

NoClassDefFoundError végzetes hiba. Akkor fordul elő, amikor a JVM nem találja az osztály definícióját, miközben megpróbálja:

  • Instantáljon egy osztályt a új kulcsszó
  • Osztály betöltése metódushívással

A hiba akkor fordul elő, amikor a fordító sikeresen lefordíthatja az osztályt, a Java futásideje azonban nem találja az osztályfájlt. Ez általában akkor történik, ha egy statikus blokk végrehajtása vagy az osztály statikus mezőinek inicializálása során van kivétel, ezért az osztály inicializálása sikertelen.

Vegyünk egy forgatókönyvet, amely a probléma újratermelésének egyik egyszerű módja. ClassWithInitErrors az inicializálás kivételt vet. Tehát, amikor megpróbálunk létrehozni egy objektumot ClassWithInitErrors, dob ExceptionInInitializerError.

Ha újra megpróbáljuk ugyanazt az osztályt betölteni, megkapjuk a NoClassDefFoundError:

public class ClassWithInitErrors {static int data = 1/0; }
public class NoClassDefFoundErrorExample {public ClassWithInitErrors getClassWithInitErrors () {ClassWithInitErrors teszt; próbáld ki a {test = new ClassWithInitErrors () parancsot; } fogás (dobható t) {System.out.println (t); } test = new ClassWithInitErrors (); visszatérő teszt; }}

Írjunk egy tesztesetet ehhez a forgatókönyvhöz:

@Test (várható = NoClassDefFoundError.class) public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError () {NoClassDefFoundErrorExample sample = new NoClassDefFoundErrorExample (); sample.getClassWithInitErrors (); }

4. Felbontás

Néha elég időigényes lehet a két probléma diagnosztizálása és kijavítása. Mindkét probléma fő oka az, hogy az osztályfájl futás közben nem érhető el (az osztályútvonalon).

Vessünk egy pillantást néhány megközelítésre, amelyet figyelembe vehetünk, ha ezek egyikét kezeljük:

  1. Meg kell győződnünk arról, hogy az osztályt tartalmazó edény vagy edény elérhető-e az osztályútvonalon. Ha nem, akkor hozzá kell adnunk
  2. Ha elérhető az alkalmazás osztályútvonalán, akkor valószínűleg az osztályút felülíródik. Ennek kijavításához meg kell találnunk az alkalmazásunk által használt pontos osztályt
  3. Továbbá, ha egy alkalmazás több osztályos rakodót használ, akkor az egyik osztályterhelő által betöltött osztályok nem biztos, hogy elérhetőek lesznek más osztályos betöltőknél. A megfelelő hibaelhárításhoz elengedhetetlen tudni, hogy az osztálytervezők hogyan működnek a Java-ban

5. Összefoglalás

Míg mindkét kivétel kapcsolódik ahhoz, hogy a classpath és a Java futásideje nem képes futtatáskor osztályt találni, fontos megjegyezni a különbségeket.

Java futásidejű dobások ClassNotFoundException miközben csak futás közben próbált betölteni egy osztályt, és a nevet futás közben adták meg. Abban az esetben NoClassDefFoundError, a osztály volt jelen a fordítás idején, de a Java futásidejű futás közben nem találta a Java osztályúton.

Mint mindig, az összes példa teljes kódja megtalálható a GitHub oldalon.