ClassNotFoundException vs NoClassDefFoundError

1. Introduksjon

Både ClassNotFoundException og NoClassDefFoundError oppstå når JVM ikke finner en ønsket klasse på klassestien. Selv om de ser kjent ut, er det noen kjerneforskjeller mellom disse to.

I denne opplæringen vil vi diskutere noen av årsakene til deres forekomst og deres løsninger.

2. ClassNotFoundException

ClassNotFoundException er et avkrysset unntak som oppstår når et program prøver å laste en klasse gjennom sitt fullstendige navn og ikke finner definisjonen på klassestien.

Dette skjer hovedsakelig når du prøver å laste klasser ved hjelp av Class.forName (), ClassLoader.loadClass () eller ClassLoader.findSystemClass (). Derfor må vi være ekstra forsiktige med java.lang.ClassNotFoundException mens du arbeider med refleksjon.

La oss for eksempel prøve å laste inn JDBC-førerklassen uten å legge til nødvendige avhengigheter som vil gi oss ClassNotFoundException:

@Test (forventet = ClassNotFoundException.class) offentlig tomrom gittNoDrivers_whenLoadDriverClass_thenClassNotFoundException () kaster ClassNotFoundException {Class.forName ("oracle.jdbc.driver.OracleDriver"); }

3. NoClassDefFoundError

NoClassDefFoundError er en dødelig feil. Det oppstår når JVM ikke finner definisjonen av klassen mens du prøver å:

  • Instantiere en klasse ved å bruke ny nøkkelord
  • Last inn en klasse med en metodeanrop

Feilen oppstår når en kompilator kunne kompilere klassen, men Java-kjøretid kunne ikke finne klassefilen. Det skjer vanligvis når det er et unntak mens du utfører en statisk blokk eller initialiserer statiske felt i klassen, slik at initialisering av klassen mislykkes.

La oss vurdere et scenario som er en enkel måte å gjengi problemet på. ClassWithInitErrors initialisering kaster et unntak. Så når vi prøver å lage et objekt av ClassWithInitErrors, det kaster ExceptionInInitializerError.

Hvis vi prøver å laste samme klasse igjen, får vi NoClassDefFoundError:

offentlig klasse ClassWithInitErrors {static int data = 1/0; }
offentlig klasse NoClassDefFoundErrorExample {offentlige ClassWithInitErrors getClassWithInitErrors () {ClassWithInitErrors test; prøv {test = new ClassWithInitErrors (); } catch (Throwable t) {System.out.println (t); } test = nye ClassWithInitErrors (); returprøve; }}

La oss skrive en test case for dette scenariet:

@Test (forventet = NoClassDefFoundError.class) offentlig ugyldig givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError () {NoClassDefFoundErrorExample sample = new NoClassDefFoundErrorExample (); sample.getClassWithInitErrors (); }

4. Oppløsning

Noen ganger kan det være ganske tidkrevende å diagnostisere og fikse disse to problemene. Hovedårsaken til begge problemene er utilgjengeligheten av klassefilen (i klassestien) ved kjøretid.

La oss se på noen tilnærminger vi kan vurdere når vi arbeider med en av disse:

  1. Vi må sørge for om klasse eller krukke som inneholder den klassen, er tilgjengelig på klassestien. Hvis ikke, må vi legge det til
  2. Hvis den er tilgjengelig på programmets klassesti, blir sannsynligvis klassesti overstyrt. For å fikse det, må vi finne den nøyaktige klassestien som brukes av applikasjonen vår
  3. Hvis et program bruker flere klasselastere, er det ikke sikkert at klasser lastet av en klasselaster er tilgjengelige av andre klasselastere. For å feilsøke det godt er det viktig å vite hvordan klasselastere fungerer i Java

5. Sammendrag

Selv om begge disse unntakene er relatert til klassesti og Java-kjøretid som ikke finner en klasse på kjøretid, er det viktig å merke seg forskjellene.

Java kjøretid kaster ClassNotFoundException mens du prøvde å laste en klasse bare ved kjøretid, og navnet ble gitt under kjøretiden. I tilfelle av NoClassDefFoundError, den klasse var til stede på kompileringstidspunktet, men Java runtime kunne ikke finne den i Java classpath under runtime.

Som alltid kan den komplette koden for alle eksempler finnes på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found