Saya mendapatkan NoClassDefFoundError
ketika saya menjalankan aplikasi Java saya. Apa yang biasanya menjadi penyebab hal ini?
Saya mendapatkan NoClassDefFoundError
ketika saya menjalankan aplikasi Java saya. Apa yang biasanya menjadi penyebab hal ini?
Jawaban:
Ini disebabkan ketika ada file kelas yang bergantung pada kode Anda dan hadir pada waktu kompilasi tetapi tidak ditemukan saat runtime. Cari perbedaan dalam waktu kelas dan runtime class build Anda.
Meskipun ada kemungkinan bahwa ini disebabkan oleh ketidakcocokan jalur kelas antara waktu kompilasi dan waktu berjalan, itu tidak selalu benar.
Penting untuk menjaga dua atau tiga pengecualian yang berbeda di kepala kita dalam kasus ini:
java.lang.ClassNotFoundException
Pengecualian ini menunjukkan bahwa kelas tidak ditemukan di classpath. Ini menunjukkan bahwa kami mencoba memuat definisi kelas, dan kelas tidak ada di classpath.
java.lang.NoClassDefFoundError
Pengecualian ini menunjukkan bahwa JVM mencari dalam struktur data definisi kelas internal untuk definisi kelas dan tidak menemukannya. Ini berbeda dengan mengatakan bahwa itu tidak dapat diambil dari classpath. Biasanya ini menunjukkan bahwa kami sebelumnya mencoba memuat kelas dari classpath, tetapi gagal karena beberapa alasan - sekarang kami mencoba menggunakan kelas lagi (dan karenanya perlu memuatnya, karena gagal terakhir kali), tetapi kami Kami bahkan tidak akan mencoba memuatnya, karena kami gagal memuatnya lebih awal (dan cukup curiga bahwa kami akan gagal lagi). Kegagalan sebelumnya bisa berupa ClassNotFoundException atau ExceptionInInitializerError (menunjukkan kegagalan dalam blok inisialisasi statis) atau sejumlah masalah lainnya. Intinya adalah, NoClassDefFoundError belum tentu merupakan masalah classpath.
Error: Could not find or load main class
, itu akan diklasifikasikan di bawah kategori kesalahan yang mana?
Berikut adalah kode untuk diilustrasikan java.lang.NoClassDefFoundError
. Silakan lihat jawaban Jared untuk penjelasan terperinci.
NoClassDefFoundErrorDemo.java
public class NoClassDefFoundErrorDemo {
public static void main(String[] args) {
try {
// The following line would throw ExceptionInInitializerError
SimpleCalculator calculator1 = new SimpleCalculator();
} catch (Throwable t) {
System.out.println(t);
}
// The following line would cause NoClassDefFoundError
SimpleCalculator calculator2 = new SimpleCalculator();
}
}
SimpleCalculator.java
public class SimpleCalculator {
static int undefined = 1 / 0;
}
SimpleCalculator
setelah membagi dengan nol? Apakah seseorang memiliki referensi ke dokumentasi resmi untuk perilaku ini?
new SimpleCalculator()
dipanggil, Anda mendapatkan ExceptionInInitializerError dengan disebabkan oleh ArithmeticException. Kali kedua Anda menelepon new SimpleCalculator()
Anda mendapatkan NoClassDefFoundError semurni yang lainnya. Intinya adalah Anda bisa mendapatkan NoClassDefFoundError karena alasan selain SimpleCalculator.class tidak berada di classpath saat runtime.
NoClassDefFoundError Di Jawa
Definisi:
Java Virtual Machine tidak dapat menemukan kelas tertentu pada saat runtime yang tersedia pada waktu kompilasi.
Jika suatu kelas hadir selama waktu kompilasi tetapi tidak tersedia dalam java classpath selama runtime.
Contoh:
Contoh sederhana dari NoClassDefFoundError adalah kelas milik file JAR yang hilang atau JAR tidak ditambahkan ke classpath atau kadang-kadang nama jar telah diubah oleh seseorang seperti dalam kasus saya salah satu kolega saya telah mengubah tibco.jar menjadi tibco_v3.jar dan programnya adalah gagal dengan java.lang.NoClassDefFoundError dan saya bertanya-tanya apa yang salah.
Coba jalankan dengan opsi -classpath secara eksplisit dengan classpath yang menurut Anda akan bekerja dan jika itu berfungsi maka itu pertanda singkat bahwa seseorang sedang menimpa classpath java.
Solusi yang memungkinkan:
Sumber:
Saya telah menemukan bahwa kadang-kadang saya mendapatkan kesalahan NoClassDefFound ketika kode dikompilasi dengan versi kelas yang tidak kompatibel yang ditemukan saat runtime. Contoh spesifik yang saya ingat adalah dengan pustaka sumbu apache. Sebenarnya ada 2 versi di classpath runtime saya dan mengambil versi yang ketinggalan zaman dan tidak kompatibel dan bukan yang benar, menyebabkan kesalahan NoClassDefFound. Ini ada di aplikasi baris perintah di mana saya menggunakan perintah yang mirip dengan ini.
set classpath=%classpath%;axis.jar
Saya bisa mendapatkannya untuk mengambil versi yang tepat dengan menggunakan:
set classpath=axis.jar;%classpath%;
Ini adalah solusi terbaik yang saya temukan sejauh ini.
Misalkan kita memiliki paket bernama org.mypackage
mengandung kelas:
dan file-file yang mendefinisikan paket ini disimpan secara fisik di bawah direktori D:\myprogram
(di Windows) atau /home/user/myprogram
(di Linux).
Struktur file akan terlihat seperti ini:
Ketika kita memanggil Java, kita tentukan nama aplikasi untuk menjalankan: org.mypackage.HelloWorld
. Namun kami juga harus memberi tahu Java ke mana harus mencari file dan direktori yang mendefinisikan paket kami. Jadi untuk meluncurkan program, kita harus menggunakan perintah berikut:
Saya menggunakan Spring Framework dengan Maven dan menyelesaikan kesalahan ini dalam proyek saya.
Ada kesalahan runtime di kelas. Saya membaca properti sebagai integer, tetapi ketika membaca nilai dari file properti, nilainya dua kali lipat.
Spring tidak memberi saya jejak stack penuh di mana runtime gagal. Itu hanya mengatakan NoClassDefFoundError
. Tetapi ketika saya mengeksekusinya sebagai aplikasi Java asli (mengeluarkannya dari MVC), ia memberikan ExceptionInInitializerError
mana penyebab sebenarnya dan bagaimana saya melacak kesalahannya.
Jawaban @ xli memberi saya wawasan tentang apa yang mungkin salah dalam kode saya.
NoClassDefFoundError
sebenarnya disebabkan oleh ExceptionInInitalizerError
, yang disebabkan oleh DateTimeParseException
). Agak menyesatkan, bukan? Saya tahu mereka mungkin memiliki alasan untuk membuatnya seperti itu, tetapi akan sangat menyenangkan untuk memiliki setidaknya petunjuk kecil, itu NoClassDefFoundError
adalah hasil dari pengecualian lain, tanpa perlu menyimpulkannya. Hanya melempar ExceptionInInitializerError
lagi akan jauh lebih jelas. Terkadang hubungan antara keduanya mungkin tidak begitu jelas.
Saya mendapatkan NoClassFoundError ketika kelas yang dimuat oleh kelas runtime tidak dapat mengakses kelas yang sudah dimuat oleh java rootloader. Karena pemuat kelas yang berbeda berada dalam domain keamanan yang berbeda (menurut java), jvm tidak akan mengizinkan kelas yang sudah dimuat oleh rootloader untuk diselesaikan dalam ruang alamat pemuat runtime.
Jalankan program Anda dengan 'java -javaagent: tracer.jar [ARGS java ANDA]'
Ini menghasilkan output yang menunjukkan kelas yang dimuat, dan loader env yang memuat kelas. Ini sangat membantu melacak mengapa kelas tidak dapat diselesaikan.
// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5
import java.lang.instrument.*;
import java.security.*;
// manifest.mf
// Premain-Class: ClassLoadTracer
// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class
// java -javaagent:tracer.jar [...]
public class ClassLoadTracer
{
public static void premain(String agentArgs, Instrumentation inst)
{
final java.io.PrintStream out = System.out;
inst.addTransformer(new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);
// dump stack trace of the thread loading class
Thread.dumpStack();
// we just want the original .class bytes to be loaded!
// we are not instrumenting it...
return null;
}
});
}
}
Satu kasus menarik di mana Anda mungkin melihat banyak NoClassDefFoundErrors
adalah ketika Anda:
throw
a RuntimeException
di static
blok kelas AndaExample
Example
static class Example {
static {
thisThrowsRuntimeException();
}
}
static class OuterClazz {
OuterClazz() {
try {
new Example();
} catch (Throwable ignored) { //simulating catching RuntimeException from static block
// DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
}
new Example(); //this throws NoClassDefFoundError
}
}
NoClassDefError
akan dibuang disertai dengan ExceptionInInitializerError
dari blok statis RuntimeException
.
Ini adalah kasus yang sangat penting ketika Anda melihat NoClassDefFoundErrors
di UIT UNIT Anda .
Dengan cara Anda "berbagi" static
eksekusi blok antara tes, tetapi inisial ExceptionInInitializerError
hanya dalam satu kasus uji. Yang pertama yang menggunakan Example
kelas yang bermasalah . Kasus uji lain yang menggunakan Example
kelas hanya akan melempar NoClassDefFoundErrors
.
Teknik di bawah ini membantu saya berkali-kali:
System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());
di mana TheNoDefFoundClass adalah kelas yang mungkin "hilang" karena preferensi untuk versi yang lebih lama dari perpustakaan yang sama yang digunakan oleh program Anda. Ini paling sering terjadi pada kasus-kasus, ketika perangkat lunak klien sedang digunakan ke wadah yang dominan, dipersenjatai dengan classloader sendiri dan berton-ton versi kuno lib paling populer.
Jika Anda telah membuat-kode (EMF, dll.) Mungkin ada terlalu banyak initialisers statis yang mengkonsumsi semua ruang stack.
Lihat pertanyaan Stack Overflow Bagaimana cara meningkatkan ukuran Java stack? .
NoClassDefFoundError
juga dapat terjadi ketika penginisialisasi statis mencoba memuat kumpulan sumber daya yang tidak tersedia di runtime, misalnya file properti yang dicoba untuk dimuat oleh kelas yang terpengaruh dari META-INF
direktori, tetapi tidak ada di sana. Jika Anda tidak menangkap NoClassDefFoundError
, kadang-kadang Anda tidak akan dapat melihat jejak tumpukan penuh; untuk mengatasinya Anda dapat menggunakan catch
klausa untuk Throwable
:
try {
// Statement(s) that cause the affected class to be loaded
} catch (Throwable t) {
Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}
for example a properties file that the affected class tries to load from the META-INF directory
. Ini sebenarnya terjadi pada saya dan saya dapat menyelesaikannya NoClassDefFoundError
dengan menambahkan file properti yang hilang. Saya menambahkan jawaban ini tepat karena orang tidak akan mengharapkan kesalahan ini dalam keadaan yang disebutkan.
static
inisialisasi ... yang memicu pengecualian yang tidak dicentang dan menyebabkan kelas init gagal. Setiap pengecualian yang tidak dicentang yang merambat dari inisialisasi statis akan melakukan itu.
static
inisialisasi gagal ), saya akan tertarik untuk melihat contoh aktual (yaitu MCVE) yang menunjukkan perilaku.
Saya mendapat kesalahan ini ketika saya menambahkan Maven dependensi dari modul lain ke proyek saya, masalah ini akhirnya diselesaikan dengan menambahkan -Xss2m
opsi JVM program saya (Ini satu megabyte secara default sejak JDK5.0). Diyakini program tidak memiliki cukup stack untuk memuat kelas.
Jika seseorang datang ke sini karena java.lang.NoClassDefFoundError: org/apache/log4j/Logger
kesalahan, dalam kasus saya itu diproduksi karena saya menggunakan log4j 2 (tapi saya tidak menambahkan semua file yang menyertainya), dan beberapa perpustakaan dependensi menggunakan log4j 1. Solusinya adalah menambahkan Log4j 1.x bridge: tabung log4j-1.2-api-<version>.jar
yang datang dengan log4j 2. Info lebih lanjut dalam migrasi log4j 2 .
Dalam kasus saya, masalahnya adalah ketidakmampuan Eclipse untuk membedakan antara dua salinan berbeda dari proyek yang sama. Saya punya satu terkunci di trunk (kontrol versi SVN) dan yang lain bekerja di satu cabang sekaligus. Saya mencoba satu perubahan dalam copy pekerjaan sebagai kasus uji JUnit, yang termasuk mengekstraksi kelas dalam pribadi menjadi kelas publik sendiri dan ketika sedang bekerja, saya membuka salinan lain dari proyek untuk melihat-lihat beberapa lainnya. bagian dari kode yang perlu diubah. Pada titik tertentu,NoClassDefFoundError
muncul keluhan bahwa kelas batin pribadi tidak ada di sana; mengklik ganda pada jejak tumpukan membawa saya ke file sumber dalam salinan proyek yang salah.
Menutup salinan trunk proyek dan menjalankan test case sekali lagi menghilangkan masalah.
Kesalahan ini dapat disebabkan oleh persyaratan versi Java yang tidak dicentang .
Dalam kasus saya, saya dapat menyelesaikan kesalahan ini, sambil membangun proyek open-source profil tinggi, dengan beralih dari Java 9 ke Java 8 menggunakan SDKMAN! .
sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu
Kemudian lakukan instalasi bersih seperti dijelaskan di bawah ini.
Saat menggunakan Maven sebagai alat build Anda, terkadang membantu - dan biasanya memuaskan, untuk melakukan build 'install' yang bersih dengan pengujian yang dinonaktifkan .
mvn clean install -DskipTests
Sekarang semuanya telah dibangun dan diinstal, Anda dapat melanjutkan dan menjalankan tes.
mvn test
Saya mendapat kesalahan NoClassDefFound ketika saya tidak mengekspor kelas pada tab "Pesanan dan Ekspor" di Java Build Path dari proyek saya. Pastikan untuk menaruh tanda centang di tab "Order and Export" dari setiap dependensi yang Anda tambahkan ke jalur pembangunan proyek. Lihat peringatan Eclipse: XXXXXXXXXXX.jar tidak akan diekspor atau dipublikasikan. Runtime ClassNotFoundExceptions dapat terjadi .
Dalam kasus saya, saya mendapatkan kesalahan ini karena ketidakcocokan dalam versi JDK. Ketika saya mencoba menjalankan aplikasi dari Intelij itu tidak berfungsi tetapi kemudian menjalankannya dari baris perintah bekerja. Ini karena Intelij berusaha menjalankannya dengan Java 11 JDK yang telah diatur tetapi pada baris perintah ia menjalankan dengan Java 8 JDK. Setelah mengalihkan pengaturan itu di bawah File> Struktur Proyek> Pengaturan Proyek> Project SDK, itu berhasil bagi saya.
Semua orang berbicara di sini tentang beberapa hal konfigurasi Java, masalah JVM dll., Dalam kasus saya kesalahannya tidak terkait dengan topik ini sama sekali dan memiliki alasan yang sangat sepele dan mudah dipecahkan: Saya memiliki anotasi yang salah pada titik akhir di Pengontrol saya ( Aplikasi Spring Boot).
Saya punya masalah menarik dengan NoClassDefFoundError di JavaEE yang bekerja dengan server Liberty. Saya menggunakan adaptor sumber daya IMS dan server.xml saya sudah memiliki adaptor sumber daya untuk imsudbJXA.rar. Ketika saya menambahkan adaptor baru untuk imsudbXA.rar, saya akan mulai mendapatkan kesalahan ini misalnya objek untuk DLIException, IMSConnectionSpec atau SQLInteractionSpec. Saya tidak tahu mengapa tetapi saya menyelesaikannya dengan membuat server.xml baru untuk pekerjaan saya hanya menggunakan imsudbXA.rar. Saya yakin menggunakan beberapa adaptor sumber daya di server.xml baik-baik saja, saya tidak punya waktu untuk melihatnya.
Java tidak dapat menemukan kelas A di runtime. Kelas A dalam proyek pakar ArtClient dari ruang kerja yang berbeda. Jadi saya mengimpor ArtClient ke proyek Eclipse saya. Dua proyek saya menggunakan ArtClient sebagai ketergantungan. Saya mengubah referensi perpustakaan ke referensi proyek untuk yang ini (Build Path -> Configure Build Path).
Dan masalahnya hilang.
Saya memiliki masalah yang sama, dan saya siap untuk beberapa jam.
Saya menemukan solusinya. Dalam kasus saya, ada metode statis yang ditentukan karena itu. JVM tidak dapat membuat objek lain dari kelas itu.
Sebagai contoh,
private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");
Saya mendapat pesan ini setelah menghapus dua file dari pustaka SRC, dan ketika saya membawanya kembali saya terus melihat pesan kesalahan ini.
Solusi saya adalah: Restart Eclipse. Sejak itu saya tidak melihat pesan ini lagi :-)
Pastikan ini cocok di module:app
dan module:lib
:
android {
compileSdkVersion 23
buildToolsVersion '22.0.1'
packagingOptions {
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 23
versionCode 11
versionName "2.1"
}
{s
dan dua }
). Bisakah kamu memperbaikinya?