Pertanyaan Apa artinya "Tidak dapat menemukan atau memuat kelas utama"?


Masalah umum yang dialami pengembang Java baru adalah bahwa program mereka gagal dijalankan dengan pesan kesalahan: Could not find or load main class ...

Apa artinya ini, apa penyebabnya, dan bagaimana seharusnya Anda memperbaikinya?


909
2017-08-07 03:02


asal


Jawaban:


Itu java <class-name> sintaks perintah

Pertama-tama, Anda perlu memahami cara yang benar untuk meluncurkan program menggunakan java (atau javaw) perintah.

Sintaks normal1 Apakah ini:

    java [ <option> ... ] <class-name> [<argument> ...]

dimana <option> adalah opsi baris perintah (dimulai dengan karakter "-"), <class-name> adalah nama kelas Java yang sepenuhnya memenuhi syarat, dan <argument> adalah argumen baris perintah arbitrer yang dilewatkan ke aplikasi Anda.
1 - Ada sintaks kedua untuk file JAR "executable" yang akan saya jelaskan di bagian bawah.

Nama yang memenuhi syarat (FQN) untuk kelas ditulis secara konvensional seperti yang Anda lakukan dalam kode sumber Java; misalnya

    packagename.packagename2.packagename3.ClassName

Namun beberapa versi dari java perintah memungkinkan Anda untuk menggunakan garis miring, bukan periode; misalnya

    packagename/packagename2/packagename3/ClassName

yang (membingungkan) terlihat seperti nama file path, tetapi tidak satu. Perhatikan bahwa istilah itu nama yang sepenuhnya memenuhi syarat adalah terminologi Java standar ... bukan sesuatu yang saya buat untuk membingungkan Anda :-)

Berikut ini contoh dari apa a java perintah harus terlihat seperti:

    java -Xmx100m com.acme.example.ListUsers fred joe bert

Di atas akan menyebabkan java perintah untuk melakukan hal berikut:

  1. Cari versi terkompilasi dari com.acme.example.ListUsers kelas.
  2. Muat kelas.
  3. Periksa apakah kelas memiliki main metode dengan tanda tangan, jenis kembali dan pengubah diberikan oleh public static void main(String[]). (Perhatikan, nama argumen metode ini TIDAK bagian dari tanda tangan.)
  4. Panggil metode yang meneruskan argumen baris perintah ("fred", "joe", "bert") sebagai a String[].

Alasan mengapa Java tidak dapat menemukan kelas

Ketika Anda mendapatkan pesan "Tidak dapat menemukan atau memuat kelas utama ...", itu berarti bahwa langkah pertama telah gagal. Itu java komando tidak dapat menemukan kelas. Dan memang, "..." dalam pesan itu akan menjadi nama kelas yang sepenuhnya memenuhi syarat bahwa java sedang mencari.

Jadi mengapa tidak dapat menemukan kelas?

Alasan # 1 - Anda membuat kesalahan dengan argumen classname

Kemungkinan penyebab pertama adalah Anda mungkin telah memberikan nama kelas yang salah. (Atau ... nama kelas yang tepat, tetapi dalam bentuk yang salah.) Mempertimbangkan contoh di atas, di sini berbagai cara yang salah untuk menentukan nama kelas:

  • Contoh # 1 - nama kelas sederhana:

    java ListUser
    

    Ketika kelas dideklarasikan dalam paket seperti com.acme.example, maka Anda harus menggunakan nama kelas lengkap termasuk nama paket di java perintah; misalnya

    java com.acme.example.ListUser
    
  • Contoh # 2 - nama file atau nama path daripada nama kelas:

    java ListUser.class
    java com/acme/example/ListUser.class
    
  • Contoh # 3 - nama kelas dengan casing salah:

    java com.acme.example.listuser
    
  • Contoh # 4 - salah ketik

    java com.acme.example.mistuser
    
  • Contoh # 5 - nama file sumber

    java ListUser.java
    
  • Contoh # 6 - Anda lupa nama kelas seluruhnya

    java lots of arguments
    

Alasan # 2 - classpath aplikasi tidak ditentukan dengan benar

Kemungkinan penyebab kedua adalah bahwa nama kelas benar, tetapi itu java perintah tidak dapat menemukan kelas. Untuk memahami ini, Anda perlu memahami konsep "classpath". Ini dijelaskan baik oleh dokumentasi Oracle:

Jadi ... jika Anda telah menentukan nama kelas dengan benar, hal berikutnya untuk diperiksa adalah Anda telah menentukan classpath dengan benar:

  1. Baca tiga dokumen terkait di atas. (Ya ... BACA mereka. Penting bahwa seorang programmer Java mengerti setidaknya dasar-dasar bagaimana mekanisme classpath Java bekerja.)
  2. Lihatlah baris perintah dan / atau variabel lingkungan CLASSPATH yang berlaku saat Anda menjalankan java perintah. Periksa apakah nama direktori dan nama file JAR sudah benar.
  3. Jika ada relatif nama path di classpath, periksa apakah mereka menyelesaikan dengan benar ... dari direktori saat ini yang berlaku saat Anda menjalankan java perintah.
  4. Periksa apakah kelas (disebutkan dalam pesan kesalahan) dapat ditemukan di efektif classpath.
  5. Perhatikan bahwa sintaks classpath adalah berbeda untuk Windows versus Linux dan Mac OS. (Pemisah classpath adalah ; pada Windows dan : pada yang lain.)

Alasan # 2a - direktori yang salah ada di classpath

Ketika Anda meletakkan direktori di classpath, ini secara tidak sengaja berhubungan dengan root dari ruang nama yang memenuhi syarat. Kelas terletak di struktur direktori di bawah root itu, dengan memetakan nama yang memenuhi syarat ke pathname. Jadi misalnya, jika "/ usr / local / acme / kelas" ada di jalur kelas, maka ketika JVM mencari kelas yang disebut com.acme.example.Foon, ia akan mencari file ".class" dengan nama path ini:

  /usr/local/acme/classes/com/acme/example/Foon.class

Jika Anda telah meletakkan "/ usr / local / acme / classes / com / acme / example" pada classpath, maka JVM tidak akan dapat menemukan kelas.

Alasan # 2b - jalur subdirektori tidak sesuai dengan FQN

Jika kelas Anda FQN adalah com.acme.example.Foon, maka JVM akan mencari "Foon.class" di direktori "com / acme / example":

  • Jika struktur direktori Anda tidak sesuai dengan penamaan paket sesuai dengan pola di atas, JVM tidak akan menemukan kelas Anda.

  • Jika Anda mencoba ganti nama sebuah kelas dengan memindahkannya, itu akan gagal juga ... tetapi stacktrace pengecualian akan berbeda.

Untuk memberikan contoh konkret, misalkan:

  • kamu ingin berlari com.acme.example.Foon kelas,
  • path file lengkapnya /usr/local/acme/classes/com/acme/example/Foon.class,
  • direktori kerja Anda saat ini /usr/local/acme/classes/com/acme/example/,

kemudian:

# wrong, FQN is needed
java Foon

# wrong, there is no `com/acme/example` folder in the current working directory
java com.acme.example.Foon

# wrong, similar to above
java -classpath . com.acme.example.Foon

# fine; relative classpath set
java -classpath ../../.. com.acme.example.Foon

# fine; absolute classpath set
java -classpath /usr/local/acme/classes com.acme.example.Foon

Catatan:

  • Itu -classpath opsi dapat disingkat menjadi -cp di sebagian besar rilis Java. Periksa entri manual masing-masing untuk java, javac dan seterusnya.
  • Pikirkan dengan hati-hati ketika memilih antara nama path absolut dan relatif dalam classpath. Ingat bahwa pathname relatif mungkin "rusak" jika direktori saat ini berubah.

Alasan # 2c - dependensi hilang dari classpath

Classpath harus menyertakan semua lain (non-sistem) kelas yang bergantung pada aplikasi Anda. (Kelas-kelas sistem terletak secara otomatis, dan Anda jarang perlu mengkhawatirkan diri Anda sendiri dengan ini.) Agar kelas utama dimuat dengan benar, JVM perlu menemukan:

(Catatan: spesifikasi JLS dan JVM memungkinkan beberapa ruang untuk JVM untuk memuat kelas "malas", dan ini dapat mempengaruhi ketika pengecualian classloader dilempar.)

Alasan # 3 - kelas telah dinyatakan dalam paket yang salah

Kadang-kadang terjadi bahwa seseorang menempatkan file kode sumber ke dalam folder yang salah di pohon kode sumber mereka, atau mereka meninggalkan package pernyataan. Jika Anda melakukan ini dalam IDE, kompilator IDE akan segera memberi tahu Anda tentang hal ini. Demikian pula jika Anda menggunakan alat membangun Java yang layak, alat ini akan berjalan javac dengan cara yang akan mendeteksi masalah. Namun, jika Anda membangun kode Java dengan tangan, Anda dapat melakukannya sedemikian rupa sehingga compiler tidak memperhatikan masalah, dan file ".class" yang dihasilkan tidak di tempat yang Anda harapkan.

Masih tidak bisa menemukan masalahnya?

Ada banyak hal yang harus diperiksa, dan mudah sekali melewatkan sesuatu. Coba tambahkan -Xdiag opsi untuk java baris perintah (sebagai hal pertama setelahnya java). Ini akan menampilkan berbagai hal tentang pemuatan kelas, dan ini dapat memberi Anda petunjuk tentang masalah sebenarnya.


Itu java -jar <jar file> sintaksis

Sintaks alternatif yang digunakan untuk file JAR "executable" adalah sebagai berikut:

  java [ <option> ... ] -jar <jar-file-name> [<argument> ...]

misalnya

  java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred

Dalam hal ini nama kelas entry-point (yaitu com.acme.example.ListUser) dan classpath ditentukan dalam MANIFEST file JAR.


IDE

Java IDE yang khas memiliki dukungan untuk menjalankan aplikasi Java di IDE JVM itu sendiri atau di JVM anak. Ini adalah umumnya kebal dari pengecualian khusus ini, karena IDE menggunakan mekanisme sendiri untuk membangun classpath runtime, mengidentifikasi kelas utama dan menciptakan java garis komando.

Namun masih mungkin untuk pengecualian ini terjadi, jika Anda melakukan hal-hal di belakang belakang IDE. Misalnya, jika sebelumnya Anda telah menyiapkan Peluncur Aplikasi untuk aplikasi Java Anda di Eclipse, dan Anda kemudian memindahkan file JAR yang berisi kelas "utama" ke tempat yang berbeda dalam sistem file tanpa memberitahu Eclipse, Eclipse tanpa disadari akan meluncurkan JVM dengan classpath yang salah.

Singkatnya, jika Anda mendapatkan masalah ini dalam IDE, periksa hal-hal seperti status IDE basi, referensi proyek rusak atau konfigurasi peluncur rusak.

Mungkin juga bagi sebuah IDE untuk menjadi bingung. IDE adalah perangkat lunak yang sangat rumit yang terdiri dari banyak bagian yang berinteraksi. Banyak dari bagian-bagian ini mengadopsi berbagai strategi caching untuk menjadikan IDE sebagai responsif secara keseluruhan. Ini kadang-kadang bisa salah, dan satu gejala yang mungkin adalah masalah ketika meluncurkan aplikasi. Jika Anda menduga ini bisa terjadi, ada baiknya memulai ulang IDE Anda.


Referensi Lain


857
2017-08-07 03:02



Jika nama kode sumber Anda adalah HelloWorld.java, kode Anda akan dikompilasi HelloWorld.class.

Anda akan mendapatkan kesalahan itu jika Anda menyebutnya menggunakan:

java HelloWorld.class

Sebaliknya, gunakan ini:

java HelloWorld

186
2018-05-21 11:06



Jika kelas Anda dalam paket, maka Anda harus melakukannya cd ke direktori utama dan jalankan menggunakan nama lengkap kelas (packageName.MainClassName).

Contoh:

Kelas saya ada di sini:

D:\project\com\cse\

Nama lengkap kelas utama saya adalah:

com.cse.Main

Jadi saya cd kembali ke direktori utama:

D:\project

Lalu, keluarkan java perintah:

java com.cse.Main

95
2018-03-06 03:20



Jika metode utama Anda ada di dalam kelas di bawah paket, Anda harus menjalankannya di atas direktori hirarkis.

Asumsikan ada file kode sumber (Main.java):

package com.test;

public class Main {

    public static void main(String[] args) {
        System.out.println("salam 2nya\n");
    }
}

Untuk menjalankan kode ini, Anda harus menempatkannya Main.Class dalam paket seperti direktori ./com/test/Main.Java. Dan dalam penggunaan direktori root java com.test.Main.


43
2017-10-27 12:07



Ketika kode yang sama berfungsi pada satu PC, tetapi ini menunjukkan kesalahan pada yang lain, solusi terbaik yang pernah saya temukan adalah kompilasi seperti berikut:

javac HelloWorld.java
java -cp . HelloWorld

36
2017-08-21 06:58



Apa yang membantu saya menentukan classpath pada command line, misalnya:

  1. Buat folder baru, C:\temp

  2. Buat file Temp.java di C:\temp, dengan kelas berikut di dalamnya:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
    
  3. Buka baris perintah di folder C:\temp, dan tulis perintah berikut untuk mengkompilasi kelas Temp:

    javac Temp.java
    
  4. Jalankan kelas Java yang dikompilasi, tambahkan -classpath pilihan untuk memberi tahu JRE di mana menemukan kelas:

    java -classpath C:\temp Temp Hello!
    

26
2017-07-02 11:11



Menurut pesan kesalahan ("Tidak dapat menemukan atau memuat kelas utama"), ada dua kategori masalah:

  1. Kelas utama tidak bisa ditemukan
  2. Kelas utama tidak bisa sarat (kasus ini tidak sepenuhnya dibahas dalam jawaban yang diterima)

Kelas utama tidak bisa ditemukan ketika ada salah ketik atau sintaks salah dalam nama kelas yang sepenuhnya memenuhi syarat atau itu tidak ada di classpath yang disediakan.

Kelas utama tidak bisa sarat kapan kelas tidak dapat dimulai, biasanya kelas utama memperluas kelas lain dan kelas itu tidak ada di classpath yang disediakan.

Sebagai contoh:

public class YourMain extends org.apache.camel.spring.Main

Jika unta-pegas tidak termasuk, kesalahan ini akan dilaporkan.


20
2017-09-17 01:35



Kadang-kadang apa yang menyebabkan masalah tidak ada hubungannya dengan kelas utama, dan saya harus menemukan ini dengan cara yang sulit. Ini adalah perpustakaan referensi yang saya pindahkan, dan itu memberi saya:

Tidak dapat menemukan atau memuat kelas utama xxx Linux

Saya baru saja menghapus referensi itu, menambahkannya lagi, dan itu berfungsi dengan baik lagi.


11
2017-11-01 18:04



Saya memiliki kesalahan seperti itu dalam kasus ini:

java -cp lib.jar com.mypackage.Main

Ia bekerja dengan ; untuk Windows dan : untuk Unix:

java -cp lib.jar; com.mypackage.Main

11
2017-09-22 07:35