Apa perbedaan antara NoClassDefFoundError
dan ClassNotFoundException
?
Apa yang menyebabkan mereka dilempar? Bagaimana mereka bisa diselesaikan?
Saya sering menemukan lemparan ini ketika memodifikasi kode yang sudah ada untuk memasukkan file jar baru. Saya telah memukul mereka di sisi klien dan sisi server untuk aplikasi java yang didistribusikan melalui webstart.
Kemungkinan alasan yang saya temui:
- paket tidak termasuk dalam
build.xml
untuk sisi kode klien - runtime classpath hilang untuk guci baru yang kami gunakan
- konflik versi dengan toples sebelumnya
Ketika saya menemukan ini hari ini saya mengambil pendekatan jejak-dan-kesalahan untuk membuat semuanya berfungsi. Saya membutuhkan lebih banyak kejelasan dan pengertian.
-verbose
(misalnya-verbose:class -verbose:jni
) membantu - tetapi mogsie melaporkan di bawah jawaban mereka bahwa ini tidak memberikan informasi tambahan yang berguna :(Jawaban:
Perbedaan dari Spesifikasi Java API adalah sebagai berikut.
Untuk
ClassNotFoundException
:Untuk
NoClassDefFoundError
:Jadi, tampak bahwa
NoClassDefFoundError
terjadi ketika sumber berhasil dikompilasi, tetapi saat runtime,class
file yang diperlukan tidak ditemukan. Ini mungkin sesuatu yang bisa terjadi dalam distribusi atau produksi file JAR, di mana tidak semuaclass
file yang diperlukan dimasukkan.Adapun
ClassNotFoundException
, tampaknya itu mungkin berasal dari mencoba membuat panggilan reflektif ke kelas saat runtime, tetapi kelas-kelas yang coba dipanggil oleh program tidak ada.Perbedaan antara keduanya adalah bahwa yang satu adalah
Error
dan yang lainnya adalahException
. DenganNoClassDefFoundError
adalahError
dan itu muncul dari Java Virtual Machine mengalami masalah menemukan kelas yang diharapkan untuk menemukan. Program yang diharapkan bekerja pada waktu kompilasi tidak dapat berjalan karenaclass
file tidak ditemukan, atau tidak sama dengan yang diproduksi atau ditemui pada waktu kompilasi. Ini adalah kesalahan yang cukup kritis, karena program tidak dapat dimulai oleh JVM.Di sisi lain, itu
ClassNotFoundException
adalahException
, jadi agak diharapkan, dan merupakan sesuatu yang dapat dipulihkan. Menggunakan refleksi dapat menjadi rawan kesalahan (karena ada beberapa harapan bahwa hal-hal mungkin tidak berjalan seperti yang diharapkan. Tidak ada pemeriksaan waktu kompilasi untuk melihat bahwa semua kelas yang diperlukan ada, sehingga setiap masalah dengan menemukan kelas yang diinginkan akan muncul saat runtime .sumber
NoClassDefFoundError
biasanya terjadi ketika ada masalah (pengecualian dilempar) dengan blok statis atau inisialisasi bidang statis kelas, sehingga kelas tidak dapat diinisialisasi dengan sukses.Error
dan yang lainnya adalahException
. :)ClassNotFoundException dilemparkan ketika kelas yang dilaporkan tidak ditemukan oleh ClassLoader. Ini biasanya berarti bahwa kelas tidak ada di CLASSPATH. Ini juga bisa berarti bahwa kelas yang dimaksud sedang mencoba untuk dimuat dari kelas lain yang dimuat dalam classloader induk dan karenanya kelas dari child classloader tidak terlihat. Ini kadang terjadi ketika bekerja di lingkungan yang lebih kompleks seperti Server Aplikasi (WebSphere terkenal karena masalah classloader tersebut).
Orang sering cenderung bingung
java.lang.NoClassDefFoundError
denganjava.lang.ClassNotFoundException
namun ada perbedaan penting. Misalnya pengecualian (kesalahan sejak itujava.lang.NoClassDefFoundError
adalah subclass dari java.lang.Error) sepertitidak berarti bahwa kelas ActiveMQConnectionFactory tidak ada di CLASSPATH. Justru sebaliknya. Ini berarti bahwa kelas ActiveMQConnectionFactory ditemukan oleh ClassLoader namun ketika mencoba memuat kelas, itu mengalami kesalahan membaca definisi kelas. Ini biasanya terjadi ketika kelas yang bersangkutan memiliki blok statis atau anggota yang menggunakan Kelas yang tidak ditemukan oleh ClassLoader. Jadi untuk menemukan pelakunya, lihat sumber kelas yang dimaksud (ActiveMQConnectionFactory dalam kasus ini) dan cari kode menggunakan blok statis atau anggota statis. Jika Anda tidak memiliki akses ke sumbernya, cukup dekompilasi menggunakan JAD.
Pada memeriksa kode, katakan Anda menemukan garis kode seperti di bawah ini, pastikan kelas SomeClass di dalam CLASSPATH Anda.
Kiat: Untuk mengetahui toples mana yang dimiliki kelas, Anda dapat menggunakan jarFinder situs web. Ini memungkinkan Anda untuk menentukan nama kelas menggunakan wildcard dan mencari kelas di database guci. jarhoo memungkinkan Anda untuk melakukan hal yang sama tetapi tidak lagi bebas untuk digunakan.
Jika Anda ingin mencari tabung yang dimiliki kelas di jalur lokal, Anda dapat menggunakan utilitas seperti jarscan ( http://www.inetfeedback.com/jarscan/ ). Anda cukup menentukan kelas yang ingin Anda temukan dan jalur direktori root di mana Anda ingin mulai mencari kelas dalam guci dan file zip.
sumber
NoClassDefFoundError
adalah kesalahan tautan pada dasarnya. Ini terjadi ketika Anda mencoba dan membuat instance suatu objek (secara statis dengan "baru") dan itu tidak ditemukan ketika itu selama kompilasi.ClassNotFoundException
lebih umum dan merupakan pengecualian runtime ketika Anda mencoba menggunakan kelas yang tidak ada. Misalnya, Anda memiliki parameter dalam fungsi yang menerima antarmuka dan seseorang lewat di kelas yang mengimplementasikan antarmuka itu tetapi Anda tidak memiliki akses ke kelas. Ini juga mencakup kasus pemuatan kelas dinamis, seperti menggunakanloadClass()
atauClass.forName()
.sumber
NoClassDefFoundError (NCDFE) terjadi ketika kode Anda menjalankan "Y baru ()" dan tidak dapat menemukan kelas Y.
Mungkin saja bahwa Y hilang dari pemuat kelas Anda seperti komentar lain yang disarankan, tetapi bisa jadi bahwa kelas Y tidak ditandatangani atau memiliki tanda tangan tidak valid, atau bahwa Y dimuat oleh classloader berbeda yang tidak terlihat oleh kode Anda , atau bahkan Y tergantung pada Z yang tidak dapat dimuat karena alasan di atas.
Jika ini terjadi, maka JVM akan mengingat hasil pemuatan X (NCDFE) dan itu hanya akan membuang NCDFE baru setiap kali Anda meminta Y tanpa memberi tahu Anda alasannya:
simpan ini sebagai a.java di suatu tempat
Kode hanya mencoba membuat instance kelas "b" baru dua kali, selain itu, tidak memiliki bug, dan tidak melakukan apa pun.
Kompilasi kode dengan
javac a.java
, Kemudian jalankan dengan memohonjava -cp . a
- itu hanya akan mencetak dua baris teks, dan itu harus berjalan dengan baik tanpa kesalahan.Kemudian hapus file "a $ b.class" (atau isi dengan sampah, atau salin a.class di atasnya) untuk mensimulasikan kelas yang hilang atau rusak. Inilah yang terjadi:
Doa pertama menghasilkan ClassNotFoundException (dilemparkan oleh pemuat kelas ketika tidak dapat menemukan kelas), yang harus dibungkus dengan NoClassDefFoundError yang tidak dicentang, karena kode yang dipermasalahkan (
new b()
) seharusnya hanya berfungsi.Upaya kedua tentu saja akan gagal juga, tetapi seperti yang Anda lihat pengecualian dibungkus tidak lebih, karena ClassLoader tampaknya ingat pemuat kelas yang gagal. Anda hanya melihat NCDFE yang sama sekali tidak tahu apa yang sebenarnya terjadi.
Jadi jika Anda pernah melihat NCDFE tanpa akar penyebab, Anda perlu melihat apakah Anda dapat melacak kembali saat pertama kali kelas dimuat untuk menemukan penyebab kesalahan.
sumber
-verbose
, atau beberapa opsi serupa tergantung pada JVM tertentu? Mungkin-verbose:class
, mungkin-verbose:class:jni
jika menggunakan JNI, tapi saya tidak yakin tentang sintaksisnya. Jika ini berguna, mungkin Anda bisa menunjukkan hasilnya.-verbose:class
tidak-verbose:jni
memberikan output tambahan yang relevan dengan kelas yang hilang.-verbose:class:jni
itu salah: kita harus menentukan dua opsi terpisah:.-verbose:class -verbose:jni
)Dari http://www.javaroots.com/2013/02/classnotfoundexception-vs.html :
ClassNotFoundException
: terjadi ketika pemuat kelas tidak dapat menemukan kelas yang diperlukan di jalur kelas. Jadi, pada dasarnya Anda harus memeriksa jalur kelas Anda dan menambahkan kelas di classpath.NoClassDefFoundError
: ini lebih sulit untuk di-debug dan menemukan alasannya. Ini dilemparkan ketika pada waktu kompilasi kelas yang diperlukan hadir, tetapi pada saat run kelas diubah atau dihapus atau statis kelas menginisialisasi melempar pengecualian. Itu berarti kelas yang mendapatkan dimuat hadir di classpath, tetapi salah satu kelas yang diperlukan oleh kelas ini dihapus atau gagal dimuat oleh kompiler. Jadi Anda harus melihat kelas-kelas yang bergantung pada kelas ini.Contoh :
Sekarang setelah mengkompilasi kedua kelas, jika Anda menghapus file Test1.class dan menjalankan kelas Test, itu akan melempar
ClassNotFoundException
: dilemparkan ketika aplikasi mencoba memuat di kelas melalui namanya, tetapi tidak ada definisi untuk kelas dengan nama yang ditentukan dapat ditemukan.NoClassDefFoundError
: dilemparkan jika Java Virtual Machine mencoba memuat dalam definisi kelas dan tidak ada definisi kelas yang dapat ditemukan.sumber
-verbose
, atau beberapa opsi serupa tergantung pada JVM tertentu? Mungkin-verbose:class
, mungkin-verbose:class:jni
jika menggunakan JNI, tapi saya tidak yakin tentang sintaksisnya.-verbose:class:jni
salah, tapi Anda dapat melewati dua pilihan yang terpisah:-verbose:class -verbose:jni
.Mereka terkait erat. A
ClassNotFoundException
terlempar ketika Jawa pergi mencari kelas tertentu dengan nama dan tidak berhasil memuatnya. ANoClassDefFoundError
terlempar ketika Java pergi mencari kelas yang ditautkan ke beberapa kode yang ada, tetapi tidak dapat menemukannya karena satu dan lain hal (misalnya, classpath yang salah, versi Java yang salah, versi perpustakaan yang salah) dan sangat fatal karena itu menunjukkan bahwa ada sesuatu yang salah.Jika Anda memiliki latar belakang C, CNFE seperti kegagalan untuk
dlopen()
/dlsym()
dan NCDFE adalah masalah dengan penghubung; dalam kasus kedua, file kelas yang bersangkutan seharusnya tidak pernah benar-benar dikompilasi dalam konfigurasi yang Anda coba gunakan.sumber
Contoh 1:
Jika
com/example/Class1
tidak ada di classpath, maka itu melemparClassNotFoundException
.Contoh # 2:
Jika
com/example/Class2
ada saat mengkompilasi B, tetapi tidak ditemukan saat eksekusi, maka itu melemparNoClassDefFoundError
.Keduanya adalah pengecualian waktu berjalan.
sumber
ClassNotFoundException dilemparkan ketika ada upaya untuk memuat kelas dengan merujuknya melalui sebuah String. Sebagai contoh, parameter untuk di Class.forName () adalah sebuah String, dan ini meningkatkan potensi nama biner yang tidak valid yang diteruskan ke classloader.
ClassNotFoundException dilemparkan ketika nama biner yang berpotensi tidak valid ditemukan; misalnya, jika nama kelas memiliki karakter '/', Anda terikat untuk mendapatkan ClassNotFoundException. Ini juga terlempar ketika kelas yang direferensikan langsung tidak tersedia di classpath.
Di sisi lain, NoClassDefFoundError terlempar
Singkatnya, NoClassDefFoundError biasanya dilemparkan pada pernyataan () baru atau pemanggilan metode yang memuat kelas yang sebelumnya tidak ada (sebagai lawan dari pemuatan kelas berbasis string untuk ClassNotFoundException), ketika classloader tidak dapat menemukan atau memuat definisi kelas ( s).
Akhirnya, tergantung pada implementasi ClassLoader untuk melempar instance dari ClassNotFoundException ketika tidak dapat memuat kelas. Sebagian besar implementasi classloader kustom melakukan ini karena mereka memperpanjang URLClassLoader. Biasanya classloaders tidak secara eksplisit melempar NoClassDefFoundError pada salah satu implementasi metode - pengecualian ini biasanya dilemparkan dari JVM di kompiler HotSpot, dan bukan oleh classloader itu sendiri.
sumber
Perbedaan Antara ClassNotFoundException Vs NoClassDefFoundError
sumber
Pengecualian: Pengecualian terjadi selama pelaksanaan program. Seorang programmer dapat menangani pengecualian ini dengan mencoba menangkap blok. Kami memiliki dua jenis pengecualian. Memeriksa pengecualian yang melempar pada waktu kompilasi. Pengecualian Runtime yang dilemparkan pada saat dijalankan, pengecualian ini biasanya terjadi karena pemrograman yang buruk.
Kesalahan: Ini bukan pengecualian sama sekali, itu di luar lingkup programmer. Kesalahan ini biasanya dilontarkan oleh JVM.
sumber gambar
Perbedaan:
ClassNotFoundException:
ClassNotFoundException
.ClassNotFoundException
adalah Pengecualian yang diperiksa berasal langsung darijava.lang.Exception
kelas dan Anda harus memberikan penanganan eksplisit untuk ituClassNotFoundException
muncul ketika ada pemuatan eksplisit kelas yang terlibat dengan memberikan nama kelas saat runtime menggunakan ClassLoader.loadClass (), Class.forName () dan ClassLoader.findSystemClass ().NoClassDefFoundError:
NoClassDefFoundError
.NoClassDefFoundError
adalah kesalahan yang berasal dariLinkageError
kelas, yang digunakan untuk menunjukkan kasus kesalahan, di mana kelas memiliki ketergantungan pada beberapa kelas lain dan kelas itu telah berubah secara tidak kompatibel setelah kompilasi.NoClassDefFoundError
adalah hasil dari pemuatan kelas implisit karena pemanggilan metode dari kelas itu atau akses variabel apa pun.Kesamaan:
NoClassDefFoundError
danClassNotFoundException
terkait dengan tidak tersedianya kelas saat run-time.ClassNotFoundException
danNoClassDefFoundError
terkait dengan classpath Java.sumber
Mengingat tindakan sussystem loader Kelas:
Ini adalah artikel yang banyak membantu saya untuk memahami perbedaannya: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html
Jadi ClassNotFoundException adalah penyebab utama dari NoClassDefFoundError .
Dan NoClassDefFoundError adalah kasus khusus kesalahan pemuatan tipe, yang terjadi pada langkah Linking .
sumber
Tambahkan satu kemungkinan alasan dalam praktik:
Dalam praktiknya, Kesalahan dapat dilemparkan secara diam - diam , misalnya, Anda mengirimkan tugas penghitung waktu dan dalam tugas penghitung waktu ia melempar Kesalahan , sementara dalam kebanyakan kasus, program Anda hanya menangkap Pengecualian . Kemudian loop utama Timer berakhir tanpa informasi apa pun. Kesalahan serupa dengan NoClassDefFoundError adalah ExceptionInInitializerError , ketika penginisialisasi statis Anda atau penginisialisasi untuk variabel statis melempar pengecualian.
sumber
ClassNotFoundException adalah pengecualian yang diperiksa yang terjadi ketika kita memberi tahu JVM untuk memuat kelas dengan nama stringnya menggunakan Class.forName () atau ClassLoader.findSystemClass () atau metode ClassLoader.loadClass () dan kelas yang disebutkan tidak ditemukan di classpath.
Sebagian besar waktu, pengecualian ini terjadi ketika Anda mencoba menjalankan aplikasi tanpa memperbarui classpath dengan file JAR yang diperlukan. Sebagai Contoh, Anda mungkin telah melihat pengecualian ini ketika melakukan kode JDBC untuk terhubung ke database Anda yaituMySQL tetapi classpath Anda tidak memiliki JAR untuk itu.
Kesalahan NoClassDefFoundError terjadi ketika JVM mencoba memuat kelas tertentu yang merupakan bagian dari eksekusi kode Anda (sebagai bagian dari panggilan metode normal atau sebagai bagian dari pembuatan instance menggunakan kata kunci baru) dan kelas itu tidak ada di classpath Anda tetapi sebelumnya hadir pada waktu kompilasi karena untuk menjalankan program Anda, Anda perlu mengkompilasinya dan jika Anda mencoba menggunakan kelas yang tidak hadir, kompiler akan meningkatkan kesalahan kompilasi.
Di bawah ini adalah deskripsi singkat
Anda dapat membaca Semuanya Tentang ClassNotFoundException Vs NoClassDefFoundError untuk lebih jelasnya.
sumber
Saya mengingatkan diri saya pada hal-hal berikut lagi dan lagi ketika saya perlu menyegarkan
ClassNotFoundException
Hirarki Kelas
Saat debugging
NoClassDefFoundError
Hirarki Kelas
Saat debugging
sumber
ClassNotFoundException dan NoClassDefFoundError terjadi ketika kelas tertentu tidak ditemukan saat runtime. Namun, mereka terjadi pada skenario yang berbeda.
ClassNotFoundException adalah pengecualian yang terjadi ketika Anda mencoba memuat kelas pada waktu berjalan menggunakan metode Class.forName () atau loadClass () dan kelas yang disebutkan tidak ditemukan di classpath.
NoClassDefFoundError adalah kesalahan yang terjadi ketika kelas tertentu hadir pada waktu kompilasi, tetapi hilang pada saat dijalankan.
Ketika Anda mengkompilasi program di atas, dua file .class akan dihasilkan. Satu adalah A.class dan satu lagi adalah B.class. Jika Anda menghapus file A.class dan menjalankan file B.class, Java Runtime System akan melempar NoClassDefFoundError seperti di bawah ini:
sumber