ClassNotFoundException vs NoClassDefFoundError

1. Perkenalan

Baik ClassNotFoundException dan NoClassDefFoundError terjadi ketika JVM tidak dapat menemukan kelas yang diminta di classpath. Meskipun terlihat familier, ada beberapa perbedaan inti di antara keduanya.

Dalam tutorial ini, kita akan membahas beberapa alasan kemunculannya dan solusinya.

2. ClassNotFoundException

ClassNotFoundException adalah pengecualian yang dicentang yang terjadi saat aplikasi mencoba memuat kelas melalui nama yang sepenuhnya memenuhi syarat dan tidak dapat menemukan definisinya di jalur kelas.

Ini terjadi terutama ketika mencoba memuat kelas menggunakan Class.forName () , ClassLoader.loadClass () atau ClassLoader.findSystemClass () . Oleh karena itu, kita perlu ekstra hati-hati terhadap java.lang.ClassNotFoundException saat bekerja dengan refleksi.

Misalnya, mari kita coba memuat kelas driver JDBC tanpa menambahkan dependensi yang diperlukan yang akan memberi kita ClassNotFoundException:

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

3. NoClassDefFoundError

NoClassDefFoundError adalah kesalahan fatal. Itu terjadi ketika JVM tidak dapat menemukan definisi kelas ketika mencoba untuk:

  • Buat instance kelas dengan menggunakan kata kunci baru
  • Memuat kelas dengan panggilan metode

Kesalahan terjadi ketika kompiler berhasil mengkompilasi kelas, tetapi runtime Java tidak dapat menemukan file kelas. Ini biasanya terjadi ketika ada pengecualian saat menjalankan blok statis atau menginisialisasi bidang statis kelas, sehingga inisialisasi kelas gagal.

Mari pertimbangkan skenario yang merupakan salah satu cara sederhana untuk mereproduksi masalah. Inisialisasi ClassWithInitErrors memunculkan pengecualian. Jadi, ketika kita mencoba untuk membuat obyek dari ClassWithInitErrors, melempar ExceptionInInitializerError.

Jika kita mencoba memuat kelas yang sama lagi, kita mendapatkan 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; } }

Mari kita tulis kasus uji untuk skenario ini:

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

4. Resolusi

Terkadang, mendiagnosis dan memperbaiki kedua masalah ini bisa sangat memakan waktu. Alasan utama untuk kedua masalah tersebut adalah tidak tersedianya file kelas (di classpath) pada waktu proses.

Mari kita lihat beberapa pendekatan yang dapat kita pertimbangkan ketika berhadapan dengan salah satu dari ini:

  1. Kita perlu memastikan apakah class atau jar yang berisi class tersebut tersedia di classpath. Jika tidak, kita perlu menambahkannya
  2. Jika ini tersedia di classpath aplikasi, kemungkinan besar classpath akan diganti. Untuk memperbaikinya kita perlu menemukan classpath yang tepat yang digunakan oleh aplikasi kita
  3. Selain itu, jika aplikasi menggunakan beberapa pemuat kelas, kelas yang dimuat oleh satu pemuat kelas mungkin tidak tersedia oleh pemuat kelas lain. Untuk memecahkan masalahnya dengan baik, penting untuk mengetahui cara kerja classloader di Java

5. Ringkasan

Meskipun kedua pengecualian ini terkait dengan classpath dan waktu proses Java tidak dapat menemukan kelas pada waktu proses, penting untuk mencatat perbedaannya.

Waktu proses Java memunculkan ClassNotFoundException saat mencoba memuat kelas hanya pada waktu proses dan nama tersebut diberikan selama waktu proses. Dalam kasus NoClassDefFoundError, kelas ada pada waktu kompilasi, tetapi waktu proses Java tidak dapat menemukannya di jalur kelas Java selama waktu proses.

Seperti biasa, kode lengkap untuk semua contoh dapat ditemukan di GitHub.