java.lang.NoClassDefFoundError: Tidak dapat menginisialisasi kelas XXX

165
public class PropHolder {
  public static Properties prop;

  static {
    //code for loading properties from file
  }
}

// Referencing the class somewhere else:
Properties prop = PropHolder.prop;

class PropHolderadalah kelas saya sendiri. Kelas berada di file JAR yang sama dari kelas utama. Jadi itu seharusnya tidak karena ada JAR yang hilang dari classpath.

Ketika saya melihat ke dalam file JAR oleh jar tf myjarfile, saya bisa melihat yang PropHolder.classtercantum di sana.

Btw: kodenya berjalan dengan baik di mesin lokal saya. Tetapi tidak bisa bekerja ketika saya menyebarkannya dengan beberapa skrip ke server Linux. Jadi saya pikir itu bukan masalah kode. Tetapi untuk beberapa alasan. proses penyebaran sangat sulit dilacak.

Apa yang bisa menjadi masalah?

Leon
sumber
Apakah struktur direktori yang sesuai dalam tabung Anda sesuai dengan paket kelas?
John B
perlu melihat beberapa sumber, banyak hal dapat menyebabkan ini. misalnya, pernyataan 'paket' tetapi file tersebut tidak benar-benar berada di jalur yang sesuai
jcomeau_ictx
3
Salah satu penyebabnya adalah pengecualian selama inisialisasi - apakah ada output kesalahan lainnya?
Michael Brewer-Davis

Jawaban:

210

Taruhan terbaik saya adalah ada masalah di sini:

static {
    //code for loading properties from file
}

Akan muncul beberapa pengecualian tanpa tertangkap terjadi dan disebarluaskan ke ClassLoader yang sebenarnya mencoba memuat kelas. Kami akan membutuhkan stacktrace untuk mengkonfirmasi ini.

Entah itu atau itu terjadi ketika membuat PropHolder.propvariabel statis.

John Vint
sumber
Saya telah menghadapi masalah yang sama berulang kali. Saya yakin itu karena staticmasalah itu. Apa yang perlu dilakukan untuk menyelesaikan masalah?
viper
1
Anda perlu mengidentifikasi pengecualian apa yang dilemparkan dari staticblok. Untuk debug, letakkan di try/catch(Exception e)sekitar seluruh blok dan catat pengecualian. Anda harus memperbaiki pengecualian itu. Biasanya pengecualian akan dicatat tetapi mungkin sulit ditemukan karena sedang dicatat selama pemuatan kelas yang mungkin terjadi sangat awal
John Vint
Ya saya menyimpan kode di try catchblok dan katanya Failed to initialize ClassA. Saya pikir ini masalah JVM. Saya me-restart sistem saya dan kemudian semuanya bekerja dengan baik. Bagaimana saya mengatasi masalah ini di masa depan tanpa me-restart sistem saya dan menyelesaikan masalah dengan solusi sederhana.
viper
Gagal menginisialisasi ClassA adalah efek samping dari sesuatu yang lain. Anda akan ingin melihat causejika tersedia. A NoClassDefFoundErrorselalu dikaitkan dengan kesalahan lain, Anda harus mencarinya di log atau mencoba untuk log lebih tepat (seperti memaksa masuk ke file baru pada sistem file)
John Vint
Akan lebih mudah dilacak jika Java akan melempar kesalahan CouldNotInitializeStaticPartOfClassError atau sesuatu. Maka kita sebagai pengembang akan tahu ke mana harus mencari.
Maarten
126

Anda mendapatkan java.lang.NoClassDefFoundErroryang TIDAK berarti bahwa kelas Anda hilang (dalam hal ini Anda akan mendapatkan java.lang.ClassNotFoundException). ClassLoader mengalami kesalahan saat membaca definisi kelas ketika mencoba membaca kelas.

Masukkan try / catch di dalam initializer statis Anda dan lihat pengecualiannya. Jika Anda membaca beberapa file di sana dan berbeda dari lingkungan lokal Anda, kemungkinan besar penyebab masalahnya (mungkin file tidak dapat ditemukan, tidak ada izin, dll.).

jeha
sumber
1
satu klarifikasi adalah bahwa meskipun NoClassDefFoundError tidak menyiratkan ClassNotFoundException, itu masih merupakan kemungkinan penyebab NoClassDefFoundError.
John Vint
1
buf jika Anda memiliki ClassNotFoundException maka ClassLoader akan / tidak pernah bisa mencoba memuat kelas, kan?
jeha
4
Kelas dapat memuat kelas lain yang tidak ditemukan. Penyebab dalam hal itu masih ClassNotFoundException
John Vint
1
Saya seharusnya mengklarifikasi, saya hanya bermaksud pengecualian. GetCause ()
John Vint
1
Yang ini sangat membantu di sini, karena saya telah menghabiskan sekitar 20 menit memverifikasi JAR (kelas yang dilaporkan milik) sudah termasuk. Begitu saya menyadari bahwa saya melihat ke arah yang salah, saya dengan mudah mengerti bahwa kemungkinan beberapa kelas penjelasan hilang dan voila, yang dilaporkan dinyatakan sebagai @Stateless, jadi saya hanya menambahkan ketergantungan yang sesuai dan dapat melanjutkan lebih jauh. Terima kasih atas tipnya!
RAM237
33

NoClassDefFoundError tidak memberikan banyak petunjuk tentang apa yang salah di dalam blok statis. Merupakan praktik yang baik untuk selalu memiliki blok seperti ini di dalam kode inisialisasi {...} statis:

static {
  try {

    ... your init code here

  } catch (Throwable t) {
    LOG.error("Failure during static initialization", t);
    throw t;
  }
}
Mark Hansen
sumber
Bagaimana melakukan ini di kotlin?
Marlon
Terima kasih telah memberikan petunjuk. Dalam kasus saya, saya mendapatkan NPE pada inisialisasi garis statis.
Abhishek
3

Saya memiliki pengecualian yang sama, ini adalah bagaimana saya memecahkan masalah:

Prasyarat:

  1. Kelas Junit (dan tes), yang memperpanjang kelas lain.

  2. ApplicationContext diinisialisasi menggunakan pegas, yang init proyek.

  3. Konteks aplikasi diinisialisasi dalam metode @Before

Larutan:

Init konteks aplikasi dari metode @BeforeClass, karena kelas induk juga memerlukan beberapa kelas yang diinisialisasi dari dalam konteks aplikasi.

Semoga ini bisa membantu.

KerenSi
sumber
2

Seperti disebutkan di atas, ini bisa menjadi beberapa hal. Dalam kasus saya, saya memiliki variabel diinisialisasi statis yang bergantung pada entri yang hilang di file properti saya. Menambahkan entri yang hilang ke file properti dan masalahnya selesai.

TriMix
sumber
1

Beberapa hari yang lalu, saya bertemu pertanyaan yang sama seperti pertanyaan Anda. Semua kode berjalan dengan baik di mesin lokal saya, tetapi ternyata kesalahan (noclassdeffound & inisialisasi). Jadi saya memposting solusi saya, tetapi saya tidak tahu mengapa, saya hanya mengajukan kemungkinan. Saya harap seseorang yang tahu akan menjelaskan ini. @ John Vint Pertama, saya akan menunjukkan masalah saya. Kode saya memiliki variabel statis dan blok statis keduanya. Ketika saya pertama kali menemukan masalah ini, saya mencoba solusi John Vint, dan mencoba menangkap pengecualian. Namun, saya tidak menangkap apa pun. Jadi saya pikir itu karena variabel statis (tapi sekarang saya tahu mereka adalah hal yang sama) dan masih belum menemukan apa pun. Jadi, saya mencoba mencari perbedaan antara mesin linux dan komputer saya. Kemudian saya menemukan bahwa masalah ini terjadi hanya ketika beberapa utas berjalan dalam satu proses (Omong-omong, mesin linux memiliki inti ganda dan proses ganda). Itu berarti jika ada dua tugas (keduanya menggunakan kode yang memiliki blok statis atau variabel) berjalan dalam proses yang sama, itu salah, tetapi jika mereka berjalan dalam proses yang berbeda, keduanya ok. Di mesin Linux, saya menggunakan

mvn -U clean  test -Dtest=path 

untuk menjalankan tugas, dan karena variabel statis saya adalah memulai sebuah wadah (atau mungkin Anda menginisialisasi classloader baru), maka itu akan tetap sampai jvm berhenti, dan jvm berhenti hanya ketika semua tugas dalam satu proses berhenti. Setiap tugas akan memulai sebuah wadah baru (atau classloader) dan itu membuat jvm bingung. Akibatnya, kesalahan terjadi. Lantas, bagaimana cara mengatasinya? Solusi saya adalah menambahkan perintah baru ke perintah pakar, dan membuat setiap tugas pergi ke wadah yang sama.

-Dxxx.version=xxxxx #sorry can't post more

Mungkin Anda sudah memecahkan masalah ini, tetapi masih berharap itu akan membantu orang lain yang mengalami masalah yang sama.

Raja monyet
sumber
Terlebih lagi, ketika kode berjalan di mesin linux, ikuti kesalahan di atas, ada masalah lain:, java.lang.ExceptionInInitializerError: nullitu artinya tidak dapat menemukan kelas di classloader, atau tidak tahu memuat yang mana (kurasa). Apakah kamu memenuhi itu?
MonkeyKing
1

Saya memiliki pengecualian yang sama - tetapi hanya ketika menjalankan dalam mode debug, ini adalah bagaimana saya memecahkan masalah (setelah 3 hari penuh): di build.gradle saya punya: "multiDexEnabled true" yang diatur di bagian defaultConfig.

        defaultConfig {
    applicationId "com.xxx.yyy"
    minSdkVersion 15
    targetSdkVersion 28
    versionCode 5123
    versionName "5123"
    // Enabling multidex support.
    multiDexEnabled true
}

tetapi ternyata ini tidak cukup. tetapi ketika saya berubah:

public class MyAppClass  extends Application 

untuk:

public class MyAppClass  extends MultiDexApplication 

ini menyelesaikannya. Semoga ini bisa membantu seseorang

Elad
sumber
0

Jika Anda mengerjakan proyek Android, pastikan Anda tidak memanggil metode statis apa pun di kelas Android mana pun. Saya hanya menggunakan JUnit + Mockito, jadi mungkin beberapa kerangka kerja lain dapat membantu Anda menghindari masalah sama sekali, saya tidak yakin.

Masalah saya memanggil Uri.parse(uriString)sebagai bagian dari penginisialisasi statis untuk pengujian unit. Kelas Uri adalah API Android, itulah sebabnya unit test build tidak dapat menemukannya. Saya mengubah nilai ini nullsebagai gantinya dan semuanya kembali normal.

umur106
sumber
0

Saya memiliki masalah yang sama :java.lang.NoClassDefFoundError: Tidak dapat menginisialisasi kelas com.xxx.HttpUtils

static {
    //code for loading properties from file
}

itu adalah masalah lingkungan. Itu berarti properti di application.yml salah atau kosong!

pengguna8503957
sumber
0

Saya mengalami masalah yang sama. Saya memulai objek kacang di blok statis seperti di bawah ini:

static {
    try{
        mqttConfiguration = SpringBootBeanUtils.<MqttConfiguration>getBean(MqttConfiguration.class);
    }catch (Throwable e){
        System.out.println(e);
    }
 }

Hanya karena proses inisiasi kacang obejct saya menyebabkan NPE, saya mendapatkan masalah. Jadi saya pikir Anda harus memeriksa blok kode statis Anda dengan hati-hati.

lai nan
sumber