Apa yang dimaksud dengan "Tidak dapat menemukan atau memuat kelas utama"?

1370

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 yang menyebabkannya, dan bagaimana Anda harus memperbaikinya?

Stephen C
sumber
37
Harap perhatikan bahwa ini adalah pertanyaan "jawab sendiri" yang dimaksudkan sebagai tanya jawab referensi umum untuk pengguna Java baru. Saya tidak dapat menemukan T&J yang ada yang mencakup hal ini secara memadai (IMO).
Stephen C

Jawaban:

1230

The java <class-name>sintaks perintah

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

Sintaks 1 yang normal adalah ini:

    java [ <options> ] <class-name> [<arg> ...]

di mana <option>ada opsi baris perintah (dimulai dengan karakter "-"), <class-name>adalah nama kelas Java yang sepenuhnya memenuhi syarat, dan <arg>merupakan argumen baris perintah sewenang-wenang yang diteruskan ke aplikasi Anda.


1 - Ada beberapa sintaks lain yang dijelaskan pada akhir jawaban ini.

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

    packagename.packagename2.packagename3.ClassName

Namun beberapa versi javaperintah memungkinkan Anda untuk menggunakan garis miring alih-alih titik; misalnya

    packagename/packagename2/packagename3/ClassName

yang (membingungkan) terlihat seperti pathname file, tetapi bukan salah satunya. Perhatikan bahwa istilah nama yang sepenuhnya memenuhi syarat adalah istilah Java standar ... bukan sesuatu yang saya buat untuk membingungkan Anda :-)

Ini adalah contoh dari bagaimana sebuah javaperintah seharusnya terlihat:

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

Di atas akan menyebabkan javaperintah untuk melakukan hal berikut:

  1. Cari versi kompilasi com.acme.example.ListUserskelas.
  2. Muat kelas.
  3. Periksa apakah kelas memiliki mainmetode dengan tanda tangan , jenis kembali dan pengubah yang diberikan oleh public static void main(String[]). (Catatan, nama argumen metode BUKAN bagian dari tanda tangan.)
  4. Sebut metode yang meneruskannya argumen baris perintah ("fred", "joe", "bert") sebagai a String[].

Alasan mengapa Java tidak dapat menemukan kelas

Ketika Anda menerima pesan "Tidak dapat menemukan atau memuat kelas utama ...", itu berarti bahwa langkah pertama telah gagal. The javaperintah tidak dapat menemukan kelas. Dan memang, "..." dalam pesan akan menjadi nama kelas berkualifikasi penuh yang javadicari.

Jadi mengapa mungkin tidak dapat menemukan kelas?

Alasan # 1 - Anda membuat kesalahan dengan argumen classname

Kemungkinan penyebab pertama adalah bahwa Anda mungkin memberikan nama kelas yang salah. (Atau ... nama kelas yang tepat, tetapi dalam bentuk yang salah.) Mengingat contoh di atas, berikut adalah 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 dalam javaperintah; misalnya

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

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

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

    java com.acme.example.mistuser
  • Contoh # 5 - nama file sumber (kecuali Java 11 atau lebih baru; lihat di bawah)

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

    java lots of arguments

Alasan # 2 - classpath aplikasi tidak ditentukan dengan benar

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

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

  1. Baca tiga dokumen yang ditautkan di atas. (Ya ... BACA mereka! Adalah 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 ketika Anda menjalankan javaperintah. Periksa apakah nama direktori dan nama file JAR sudah benar.
  3. Jika ada nama path relatif di classpath, periksa apakah mereka menyelesaikan dengan benar ... dari direktori saat ini yang berlaku ketika Anda menjalankan javaperintah.
  4. Periksa bahwa kelas (disebutkan dalam pesan kesalahan) dapat ditemukan di classpath yang efektif .
  5. Perhatikan bahwa sintaks classpath berbeda untuk Windows versus Linux dan Mac OS. (Pemisah classpath adalah ;pada Windows dan :yang lainnya. Jika Anda menggunakan pemisah yang salah untuk platform Anda, Anda tidak akan mendapatkan pesan kesalahan yang eksplisit. Sebaliknya, Anda akan mendapatkan file atau direktori yang tidak ada di jalur yang akan diabaikan secara diam-diam .)

Alasan # 2a - direktori yang salah ada di classpath

Ketika Anda meletakkan direktori di classpath, secara tidak langsung sesuai dengan akar ruang nama yang memenuhi syarat. Kelas-kelas terletak di struktur direktori di bawah root itu, dengan memetakan nama yang sepenuhnya memenuhi syarat untuk pathname . Jadi misalnya, jika "/ usr / local / acme / classes" ada di jalur kelas, maka ketika JVM mencari kelas yang dipanggil com.acme.example.Foon, itu akan mencari file ".class" dengan pathname ini:

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

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

Alasan # 2b - jalur subdirektori tidak cocok dengan FQN

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

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

  • Jika Anda mencoba mengubah nama kelas dengan memindahkannya, itu akan gagal juga ... tetapi stacktrace pengecualian akan berbeda. Dimaksudkan untuk mengatakan sesuatu seperti ini:

    Caused by: java.lang.NoClassDefFoundError: <path> (wrong name: <name>)

    karena FQN dalam file kelas tidak cocok dengan apa yang diharapkan oleh loader kelas.

Untuk memberikan contoh nyata, seandainya:

  • Anda ingin menjalankan com.acme.example.Foonkelas,
  • path file lengkapnya adalah /usr/local/acme/classes/com/acme/example/Foon.class,
  • direktori kerja Anda saat ini adalah /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:

  • The -classpathpilihan dapat disingkat menjadi -cpdi sebagian besar rilis Java. Periksa entri manual masing-masing untuk java, javacdan seterusnya.
  • Pikirkan baik-baik ketika memilih antara nama path absolut dan relatif di classpath. Ingat bahwa nama path relatif dapat "pecah" jika direktori saat ini berubah.

Alasan # 2c - dependensi hilang dari classpath

Kebutuhan classpath untuk memasukkan semua lainnya (non-sistem) kelas bahwa aplikasi Anda tergantung pada. (Kelas-kelas sistem terletak secara otomatis, dan Anda jarang perlu mengkhawatirkan diri Anda dengan ini.) Untuk kelas utama memuat dengan benar, JVM perlu menemukan:

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

Alasan # 3 - kelas telah dinyatakan dalam paket yang salah

Kadang-kadang terjadi bahwa seseorang meletakkan file kode sumber ke folder yang salah di pohon kode sumber mereka, atau mereka meninggalkan packagedeklarasi. Jika Anda melakukan ini dalam IDE, kompiler IDE akan segera memberi tahu Anda tentang hal ini. Demikian pula jika Anda menggunakan alat Java build yang layak, alat tersebut akan berjalan javacdengan cara yang akan mendeteksi masalah. Namun, jika Anda membuat kode Java dengan tangan, Anda dapat melakukannya sedemikian rupa sehingga kompiler tidak melihat masalah, dan file ".class" yang dihasilkan tidak berada di tempat yang Anda harapkan.

Masih tidak dapat menemukan masalahnya?

Ada banyak hal untuk diperiksa, dan mudah untuk melewatkan sesuatu. Coba tambahkan -Xdiagopsi ke javabaris perintah (sebagai yang pertama setelah java). Ini akan menampilkan berbagai hal tentang pemuatan kelas, dan ini mungkin memberi Anda petunjuk tentang apa masalah sebenarnya.

Juga, pertimbangkan kemungkinan masalah yang disebabkan oleh menyalin dan menempelkan karakter yang tidak terlihat atau non-ASCII dari situs web, dokumen, dan sebagainya. Dan perhatikan "homoglyphs", apakah dua huruf atau simbol terlihat sama ... tetapi tidak.

Akhirnya, Anda tampaknya dapat mengalami masalah ini jika Anda mencoba meluncurkan dari file JAR dengan tanda tangan yang salah di (META-INF/*.SF).


Sintaks alternatif untuk java

Ada tiga sintaks alternatif untuk meluncurkan program Java menggunakan java command.

1) Sintaks yang digunakan untuk meluncurkan file JAR "yang dapat dieksekusi" adalah sebagai berikut:

  java [ <options> ] -jar <jar-file-name> [<arg> ...]

misalnya

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

Nama kelas entry-point (yaitu com.acme.example.ListUser) dan classpath ditentukan dalam MANIFEST file JAR.

2) Sintaks untuk meluncurkan aplikasi dari modul (Java 9 dan yang lebih baru) adalah sebagai berikut:

  java [ <options> ] --module <module>[/<mainclass>] [<arg> ...]

Nama kelas entrypoint didefinisikan dengan <module>sendirinya, atau diberikan oleh opsional <mainclass>.

3) Dari Java 11 dan seterusnya, Anda dapat mengkompilasi dan menjalankan file kode sumber tunggal dan menjalankannya dengan sintaks berikut:

  java [ <options> ] <sourcefile> [<arg> ...]

di mana (biasanya) file dengan akhiran ".java".

Untuk detail lebih lanjut, silakan merujuk ke dokumentasi resmi untuk javaperintah untuk rilis Java yang Anda gunakan.


IDE

IDE Java biasanya memiliki dukungan untuk menjalankan aplikasi Java di IDE JVM itu sendiri atau di JVM anak. Ini umumnya kebal dari pengecualian khusus ini, karena IDE menggunakan mekanisme sendiri untuk membangun classpath runtime, mengidentifikasi kelas utama dan membuat javabaris perintah.

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

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

Dimungkinkan juga bagi suatu IDE untuk bingung. IDE adalah perangkat lunak yang sangat rumit yang terdiri dari banyak bagian yang saling berinteraksi. Banyak dari bagian ini mengadopsi berbagai strategi caching untuk membuat IDE secara keseluruhan responsif. Ini kadang-kadang bisa salah, dan satu gejala yang mungkin adalah masalah saat meluncurkan aplikasi. Jika Anda menduga ini bisa terjadi, ada baiknya mencoba hal-hal lain seperti memulai ulang IDE Anda, membangun kembali proyek dan sebagainya.


Referensi Lainnya

Stephen C
sumber
43
Saya memiliki masalah ini ketika saya mencoba menjalankan Kelas dengan perpustakaan pihak ke-3. Saya memohon java seperti ini java -cp ../third-party-library.jar com.my.package.MyClass:; ini tidak berfungsi, sebagai gantinya perlu menambahkan folder lokal ke jalur kelas juga (dipisahkan oleh :, seperti ini java -cp ../third-party-library.jar:. com.my.package.MyClass
:,
23
Setelah bertahun-tahun pemrograman java saya masih berhasil berakhir di halaman ini. Bagi saya masalahnya adalah sintaks classpath tergantung pada OS . Saya agak baru dalam pemrograman pada Windows dan tidak tahu.
keyser
5
Catatan tambahan, point 2 selamatkan aku! Sangat menyedihkan melihat bahwa javatidak mengatakan itu tidak menemukan kelas yang diimpor, tetapi kelas utama yang Anda coba jalankan. Ini menyesatkan, meskipun saya yakin ada alasan untuk itu. Saya memiliki kasus di mana javatahu persis di mana kelas saya, tetapi tidak dapat menemukan salah satu kelas yang diimpor. Alih-alih mengatakan itu, ia mengeluh tidak menemukan kelas utama saya. Sungguh, mengumumkan.
MSX
Saya memiliki masalah ini dua kali di Eclipse. Pertama kali tanda tangan main () salah. Kedua kalinya saya mengganti nama .jar, dan meskipun saya menambahkan yang baru ke jalur build, Eclipse tidak menemukan yang lama, jadi proyek tidak dikompilasi, dengan kesalahan ini. Saya harus menghapus file .jar dari Project> Properties> Java Build Path> Libraries.
Greg
Saya sudah menemukannya untuk ketiga kalinya. Saya sudah menjalankan program dari file batch Windows 10, dan meletakkan nama .jar dalam sebuah variabel (disebut dengan "-cp% jarname%; lib *"). Saya keliru menempatkan ruang ekstra di ujung jarname, dan itu menyebabkan kesalahan. Hat trick :)
GregT
239

Jika nama kode sumber Anda adalah HelloWorld.java, kode kompilasi Anda adalah HelloWorld.class.

Anda akan mendapatkan kesalahan itu jika Anda menyebutnya menggunakan:

java HelloWorld.class

Sebaliknya, gunakan ini:

java HelloWorld
panoet
sumber
3
Masalahnya adalah bahwa solusi ini hanya berfungsi untuk kelas Java yang dideklarasikan dalam paket default tanpa ketergantungan file JAR. (Dan bahkan kemudian, tidak setiap saat.) Sebagian besar program Java tidak sesederhana itu.
Stephen C
1
seperti kata Stephen, ini hanya berfungsi dengan "paket default" - yang berarti tidak ada deklarasi paket di bagian atas file. Untuk tes cepat beberapa kode, saya lakukan: javac TestCode.javadiikuti olehjava TestCode
Seseorang di suatu tempat
Ini tidak berhasil untuk saya. Ia masih mengatakan, "Tidak dapat menemukan atau memuat kelas utama HelloWorld"
Jim
java -jar HelloWorld.jar juga merupakan opsi
BMaximus
12
Yang perlu saya lakukanjava -classpath . HelloWorld
Chris Prince
136

Jika kelas Anda dalam paket maka Anda harus ke cddirektori root proyek Anda dan menjalankan menggunakan nama kelas yang memenuhi syarat (packageName.MainClassName).

Contoh:

Kelas saya ada di sini:

D:\project\com\cse\

Nama yang sepenuhnya memenuhi syarat dari kelas utama saya adalah:

com.cse.Main

Jadi saya cdkembali ke direktori proyek root:

D:\project

Kemudian berikan javaperintah:

java com.cse.Main

Jawaban ini adalah untuk menyelamatkan programmer java pemula dari frustrasi yang disebabkan oleh kesalahan umum, saya sarankan Anda membaca jawaban yang diterima untuk lebih banyak pengetahuan mendalam tentang classpath java.

thewinduwijewardane
sumber
2
Jawaban ini membuat banyak asumsi. Dan ada cara lain untuk mencapai ini. Alih-alih secara membabi buta mengikuti saran di atas, saya akan merekomendasikan bahwa orang meluangkan waktu untuk membaca tautan dalam Jawaban saya yang menjelaskan cara kerja classpath Java. Lebih baik MEMAHAMI apa yang Anda lakukan ...
Stephen C
2
Jawaban ini membuat asumsi tepat yang saya butuhkan :) Saya berada di direktori file .class dan java.exe tidak berfungsi. Setelah saya cd-ed di atas dan berlari dengan nama paket yang termasuk dalam baris perintah itu berhasil.
Nick Constantine
61

Jika Anda mendefinisikan kelas utama dan metode utama dalam apackage , Anda harus menjalankannya di direktori hierarkis, menggunakan nama lengkap kelas ( packageName.MainClassName).

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 menempatkan Main.Classdalam direktori paket seperti ./com/test/Main.Java. Dan dalam penggunaan direktori root java com.test.Main.

M-Razavi
sumber
1
Lihat "Catatan Tambahan # 1" dari Jawaban saya. Untuk penjelasan yang lebih baik tentang masalah ini.
Stephen C
14
@StephenC Ya, jawaban Anda lebih lengkap (dan tentu saja, +1), tetapi jawaban khusus ini memiliki kata "paket" di dalamnya, yang memungkinkan saya menemukan apa yang saya butuhkan dengan cepat. Dan itu berhasil. Jadi +1 Razavi. StephenC, Anda tidak memiliki contoh paket sederhana yang saya butuhkan karena saya baru di Jawa.
kmort
5
Ini persis masalah saya. Saya telah mengarungi berton-ton dokumen Java dan contoh konkrit inilah yang saya butuhkan
John
1
Ya, contoh nyata itu bagus, ini bekerja dengan sempurna. Saya yakin jawaban utamanya sangat teliti, tetapi sulit melihat pohon untuk hutan. Nice one @Razavi
Pixel
1
Saya suka jawaban yang lebih pendek dan bermanfaat ini daripada yang diterima!
Spara
46

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

javac HelloWorld.java
java -cp . HelloWorld
Enamul Hassan
sumber
2
Ini bukan rekomendasi yang bagus. Anda bergantung pada variabel lingkungan CLASSPATH yang tidak disetel, atau memiliki nilai yang konsisten dengan ".". Ya, itu berfungsi dalam banyak kasus, tetapi tidak dalam kasus lain.
Stephen C
Yah pasti javac -classpath . HelloWorld.javaakan berhasil! Dan itu adalah solusi yang lebih baik dalam kasus Anda.
Stephen C
2
Jika Anda memiliki 'package com.some.address' sebagai baris pertama - ini tidak akan berfungsi. Anda perlu mengomentari 'alamat paket' ..
Joe
1
@ Jo - Retas itu (mengomentari paket) akan bekerja (dalam beberapa kasus) tetapi itu adalah ide yang buruk. Ide yang lebih baik adalah mempelajari / memahami apa yang menyebabkan masalah dan mengimplementasikan solusi yang benar.
Stephen C
36

Yang membantu saya adalah menentukan classpath pada baris perintah, 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 terkompilasi, tambahkan -classpathopsi untuk memberi tahu JRE di mana menemukan kelas:

    java -classpath C:\temp Temp Hello!
Celebes
sumber
3
Di Ubuntu, saya juga harus menentukan path. Tidak mengerti mengapa itu tidak dapat menggunakan Direktori Kerja Saat Ini secara default. Saya yakin bahwa Java disponsori oleh produsen Keyboard !!
pergi
1
@ berlalu - Alasannya "." tidak dalam $ PATH secara default adalah itu adalah perangkap keamanan. seas.upenn.edu/cets/answers/dot-path.html
Stephen C
Terima kasih banyak untuk ini ...... meskipun tidak yakin mengapa java tidak bisa mengetahui classpath bahkan setelah menetapkannya dalam variabel lingkungan.
akash89
@ akash89 - Alasan yang paling mungkin adalah: 1) javatidak melihat $ CLASSPATH (karena Anda menggunakan -classpath atau -jar) atau 2) pengaturan classpath tidak disetel di lingkungan yang tidak berpengaruh dalam konteks yang javasebelumnya Lari; misalnya karena Anda tidak "sumber" file di mana menambahkan perintah setenv di shell kanan.
Stephen C
Saya masih mendapat Galat: Tidak dapat menemukan atau memuat Temp kelas utama yang dapat membantu!
Bintang
27

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

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

Kelas utama tidak dapat ditemukan ketika ada kesalahan ketik atau sintaks yang salah dalam nama kelas yang memenuhi syarat atau tidak ada dalam classpath yang disediakan .

Kelas utama tidak dapat dimuat ketika 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 pegas unta tidak termasuk, kesalahan ini akan dilaporkan.

Xiao Peng - ZenUML.com
sumber
"Pada dasarnya" ada banyak kategori lain juga. Dan masalah superclass yang hilang adalah subcase yang sangat tidak biasa. (Sangat tidak biasa sehingga saya belum pernah melihatnya ... dalam pertanyaan yang diajukan di situs ini.)
Stephen C
Ada DUA karena kesalahan mengatakan "Tidak dapat MENCARI atau LOAD kelas utama". Jika ada kategori lain, tolong beri tahu saya. Saya sudah melihatnya, jadi hanya ingin membagikannya di sini mungkin orang lain akan membutuhkannya.
Xiao Peng - ZenUML.com
1
Saya akan merevisinya menjadi sesuatu seperti "Anda harus memasukkan semua kelas yang diperlukan untuk memulai kelas utama untuk menghindari kesalahan khusus ini". Saya tidak berusaha meyakinkan Anda. Itu hanya cara yang ingin saya lihat. Saya meninggalkan jawabannya di sini hanya untuk orang-orang yang mungkin suka membaca sesuatu dengan cara ini. Mari kita tidak memperpanjang diskusi ini lebih lanjut :) Saya mengubah pernyataan saya menjadi "tidak sepenuhnya dibahas dalam jawaban yang diterima" dan saya harap Anda merasa lebih baik.
Xiao Peng - ZenUML.com
5
Informasi ini sangat penting dan pantas disebutkan secara eksplisit (ini adalah satu-satunya jawaban yang menyebutkan extends). Saya baru saja belajar dengan cara yang sulit bahwa ketika kelas utama gagal memuat karena memperluas yang lain yang tidak dapat ditemukan , java tidak melaporkan kelas mana yang sebenarnya tidak ditemukan (tidak seperti NoClassDefFoundError). Jadi ya itu memang terjadi, dan ini adalah situasi yang menarik ketika Anda tidak tahu ini.
Hugues M.
1
Dalam situasi ini apakah ada cara untuk mengetahui dengan pasti kelas dependensi mana yang gagal dimuat?
Carlos A. Ibarra
16

Saya memiliki kesalahan dalam hal ini:

java -cp lib.jar com.mypackage.Main

Ini berfungsi dengan ;untuk Windows dan :untuk Unix:

java -cp lib.jar; com.mypackage.Main
Yamahar1sp
sumber
Iya. Kemungkinan besar karena Anda Maintidak ada dalam file JAR. -cp lib.jar;berarti hal yang sama -cp lib.jar;. dengan direktori saat ini disertakan pada classpath.
Stephen C
Akhirnya memperbaiki masalah untuk unix .. terima kasih (bekerja dengan :)
Vicky
16

Coba -diag .

Jawaban Steve C mencakup semua kemungkinan kasus dengan baik, tetapi kadang-kadang untuk menentukan apakah kelas tidak dapat ditemukan atau dimuat mungkin tidak semudah itu. Gunakan java -Xdiag(sejak JDK 7). Ini mencetak stacktrace bagus yang memberikan petunjuk tentang apa arti pesan Could not find or load main classpesan.

Misalnya, ini dapat mengarahkan Anda ke kelas lain yang digunakan oleh kelas utama yang tidak dapat ditemukan dan mencegah kelas utama untuk dimuat.

jan.supol
sumber
16

Gunakan perintah ini:

java -cp . [PACKAGE.]CLASSNAME

Contoh: Jika nama kelas Anda adalah Hello.class dibuat dari Hello.java kemudian gunakan perintah di bawah ini:

java -cp . Hello

Jika file Anda Hello.java ada di dalam paket com.demo maka gunakan perintah di bawah ini

java -cp . com.demo.Hello

Dengan JDK 8 berkali-kali terjadi bahwa file kelas hadir di folder yang sama, tetapi javaperintah mengharapkan classpath dan untuk alasan ini kami menambahkan -cp .untuk mengambil folder saat ini sebagai referensi untuk classpath.

shaILU
sumber
Ini hanya berfungsi dalam kasus sederhana. Kasus yang lebih rumit memerlukan classpath yang lebih rumit.
Stephen C
Dan untuk >> sungguh << case sederhana, -cp .tidak perlu, karena jika $CLASSPATHtidak disetel, maka .adalah classpath default.
Stephen C
Tidak Stephen, berkali-kali di classpath default Windows tidak berfungsi. Saya mencobanya pada tiga mesin yang berbeda, Anda dapat mencobanya juga.
shaILU
Itu mungkin karena Anda sebenarnya telah menetapkan variabel lingkungan% CLASSPATH% di suatu tempat. Jika Anda melakukannya, maka Anda tidak menggunakan classpath default. (Apa artinya echo %CLASSPATH%keluaran?) Dan tidak, saya tidak dapat memeriksa karena saya tidak memiliki PC Windows.
Stephen C
2
Ini bekerja untuk saya ketika saya mencoba menjalankan program sederhana dari command line
SnuKies
15

Kadang-kadang apa yang menyebabkan masalah tidak ada hubungannya dengan kelas utama, dan saya harus menemukan ini dengan cara yang sulit. Itu adalah pustaka referensi yang saya pindah, dan memberi saya:

Tidak dapat menemukan atau memuat xxx kelas utama Linux

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

Eduardo Dennis
sumber
1
Kedengarannya masalahnya adalah Anda memiliki classpath yang salah karena "referensi" yang rusak dalam proyek Anda di IDE Anda. Saya akan memperbarui jawaban saya untuk membahas hal itu.
Stephen C
@StephenC dan EduardoDennis, Di sini juga, ada botol yang hilang, botol itu berisi antarmuka yang bergantung pada kelas utama untuk dipakai. Jadi, pesan kesalahannya terlalu luas. Saya harus mengatakan "tidak dapat menemukan" jika file kelas tidak ditemukan dan "tidak dapat memuat (dependensi yang hilang)" jika ada sesuatu yang hilang tetapi bukan file itu sendiri, jadi pesan kesalahan yang terlalu luas itu menyesatkan jika Anda hanya fokus pada bagian "temukan" :(
Aquarius Power
@AquariusPower - Seharusnya ada stacktrace "disebabkan oleh" tambahan untuk pengecualian "penyebab" yang mengatakan bahwa kelas apa yang hilang. Jika Anda ingin menyarankan kepada pengembang Java bahwa mereka mengubah pesan kesalahan yang telah mengatakan bahwa selama 20+ tahun ... jangan ragu. (Saya pikir pesan kesalahannya benar. Masalahnya adalah bahwa >> Anda << mempersempit klausa yang salah.)
Stephen C
@StephenC yang saya maksudkan adalah, mereka pasti memiliki akses ke informasi jika file kelas utama tersedia atau tidak, jadi mengapa tidak menunjukkan kepada kami pesan kesalahan yang lebih baik yang mengatakan bahwa file tersebut hilang. Di sisi lain, mereka juga dapat mengatakan "File itu ditemukan tetapi tidak dapat dimuat" pada saat itu, kami akan segera fokus pada dependensi alih-alih kehilangan setengah hari meneliti dan menguji hal-hal yang perlu dipahami. Hanya yang saya maksudkan :). Mereka mungkin melakukannya dengan cara terbatas selama 20+ tahun, tetapi mereka dapat memperbaikinya dan kami di sini untuk memberikan itu akan terjadi melalui kritik dan keluhan kami! : D
Aquarius Power
Tolong mengerti apa yang saya maksud <<. Mengeluh tentang hal itu dalam beberapa komentar tidak jelas tentang Q&A berusia 3 tahun tidak akan mencapai apa-apa. Orang-orang yang mungkin bertindak berdasarkan keluhan Anda tidak akan menyadarinya. Jika Anda ingin melakukan sesuatu yang konstruktif, kirimkan tambalan. (Saya tidak menilai peluang Anda, tetapi mereka akan lebih besar daripada jika Anda hanya mengomel tentang hal itu.)
Stephen C
10

Dalam hal ini Anda memiliki:

Tidak dapat menemukan atau memuat kelas utama ?

Itu karena Anda menggunakan "-classpath", tetapi tanda hubung tidak sama dengan tanda hubung yang digunakan javapada command prompt. Saya mengalami masalah menyalin dan menempel dari Notepad ke cmd.

Nathan Williams
sumber
2
Wow! Itu adalah penyebab yang benar-benar aneh! (Tapi itu berfungsi tepat untuk Anda menggunakan Notepad daripada editor teks nyata :-))
Stephen C
10

Saya memiliki masalah yang sama dan akhirnya menemukan kesalahan saya :) Saya menggunakan perintah ini untuk kompilasi dan bekerja dengan benar:

javac -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode.java

Tetapi perintah ini tidak berfungsi untuk saya (saya tidak dapat menemukan atau memuat kelas utama, qrcode):

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode

Akhirnya saya baru saja menambahkan karakter ':' di akhir classpath dan masalahnya selesai:

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar:" qrcode
Omid Mohebbi
sumber
7

Dalam kasus saya, kesalahan muncul karena saya telah memberikan nama file sumber bukan nama kelas.

Kita perlu menyediakan nama kelas yang berisi metode utama ke juru bahasa.

KawaiKx
sumber
Iya. Lihat contoh saya # 2 dari cara yang salah untuk menentukan nama kelas !!
Stephen C
7

Ini mungkin membantu Anda jika kasus Anda secara khusus seperti milik saya: sebagai pemula saya juga mengalami masalah ini ketika saya mencoba menjalankan program Java.

Saya mengkompilasinya seperti ini:

javac HelloWorld.java

Dan saya mencoba menjalankan juga dengan ekstensi yang sama:

java Helloworld.java

Ketika saya menghapus .javadan menulis ulang perintah seperti java HelloWorld, program berjalan dengan sempurna. :)

Ramesh Pareek
sumber
2
Ini karena Anda menjalankan versi kompilasi .java Anda. Ini sebenarnya mengeksekusi file .class
Jason V
Sebagai catatan, ini sama dengan Alasan # 1, Contoh # 5 dalam Jawaban saya ...
Stephen C
6

Sepertinya semua jawaban di sini ditujukan untuk pengguna Windows. Untuk Mac, pemisah classpath adalah :, tidak ;. Sebagai pengaturan kesalahan classpath menggunakan ;tidak dibuang maka ini bisa sulit ditemukan jika datang dari Windows ke Mac.

Ini adalah perintah Mac yang sesuai:

java -classpath ".:./lib/*" com.test.MyClass

Di mana dalam contoh ini paketnya com.testdan sebuah libfolder juga akan dimasukkan pada classpath.

langit biru
sumber
2
Di Linux sama seperti di Mac.
Alex78191
Mengapa /*perlu?
Alex78191
Ini adalah sintaksis wildcard. (Ini tidak wajib. Anda dapat secara eksplisit mendaftar JAR jika Anda mau.)
Stephen C
6

masukkan deskripsi gambar di sini

Lokasi file kelas: C: \ test \ com \ company

Nama File: Main.class

Nama kelas yang sepenuhnya memenuhi syarat: com.company.Main

Perintah baris perintah:

java  -classpath "C:\test" com.company.Main

Perhatikan di sini bahwa jalur kelas TIDAK termasuk \ com \ company

developer747
sumber
6

Saya menghabiskan banyak waktu untuk menyelesaikan masalah ini. Saya pikir saya entah bagaimana cara mengatur classpath saya salah tetapi masalahnya adalah saya mengetik:

java -cp C:/java/MyClasses C:/java/MyClasses/utilities/myapp/Cool  

dari pada:

java -cp C:/java/MyClasses utilities/myapp/Cool   

Saya pikir arti sepenuhnya memenuhi syarat berarti untuk memasukkan nama path lengkap, bukan nama paket lengkap.

sekolah matematika
sumber
Saya telah memperbarui jawaban saya untuk mencoba mengatasi kebingungan itu.
Stephen C
2
Tak satu pun dari ini benar. Kelas harus diberikan sebagai utilities.myapp.Coolatau apa pun nama paketnya, jika ada.
Marquis of Lorne
5

Pertama-tama setel path menggunakan perintah ini;

set path="paste the set path address"

Maka Anda perlu memuat program. Ketik "cd (nama folder)" di drive yang disimpan dan kompilasi. Sebagai Contoh, jika program saya disimpan di drive D, ketik "D:" tekan enter dan ketik "cd (nama folder)".

arun
sumber
4
Ini tidak membantu. Pertanyaan ini adalah tentang program Java, bukan executable biasa. Java tidak menggunakan PATH untuk menemukan apa pun, dan jika "cd" membantu maka itu karena keberuntungan, bukan oleh penilaian.
Stephen C
if "cd" helps then it by luck rather than by judgement. Ini salah (saya percaya), karena java menggunakan direktori saat ini .sebagai bagian dari classpath secara default.
GKFX
2
@GKFX - Itulah yang saya maksud. Kecuali Anda tahu bahwa Anda menggunakan classpath default (atau classpath dengan "." Di atasnya), "cd" tidak akan berpengaruh. Solusi ini berfungsi lebih karena keberuntungan (yaitu menebak / berharap bahwa "." Ada di classpath) daripada dengan penilaian (yaitu memeriksa bahwa "." Ada di classpath). Selain itu, Anda salah tentang default. Java menggunakan "." sebagai classpath secara default, bukan sebagai bagian dari classpath secara default.
Stephen C
5

Apa yang memperbaiki masalah dalam kasus saya adalah:

Klik kanan pada proyek / kelas yang ingin Anda jalankan, lalu Run As-> Run Configurations. Maka Anda harus memperbaiki konfigurasi yang ada atau menambahkan yang baru dengan cara berikut:

buka Classpathtab, klik Advanced...tombol lalu tambahkan binfolder proyek Anda.

syntagma
sumber
5

Jika Anda menggunakan Maven untuk membangun file JAR, pastikan untuk menentukan kelas utama dalam file pom.xml:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>class name us.com.test.abc.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>
Junchen Liu
sumber
4

Ini adalah kasus khusus, tetapi karena saya datang ke halaman ini untuk mencari solusi dan tidak menemukannya, saya akan menambahkannya di sini.

Windows (diuji dengan 7) tidak menerima karakter khusus (seperti á) di kelas dan nama paket. Linux melakukannya.

Saya menemukan ini ketika saya membangun .jardi NetBeans dan mencoba menjalankannya di command line. Itu berjalan di NetBeans tetapi tidak di baris perintah.

GuiRitter
sumber
4

Di Windows, masukkan .;nilai CLASSPATH di awal.

. (titik) berarti "lihat di direktori saat ini". Ini solusi permanen.

Anda juga dapat mengaturnya "satu kali" dengan set CLASSPATH=%CLASSPATH%;.. Ini akan berlangsung selama jendela cmd Anda terbuka.

Nenad Bulatovic
sumber
1
Nasihat ini mungkin membantu atau tidak. Ini akan membantu jika pohon kelas berisi kelas-kelas dalam direktori saat ini. Tidak akan terjadi jika tidak. Saya sebenarnya tidak akan melakukan ini. Alih-alih, saya akan membuat skrip pembungkus satu-liner yang berfungsi baik pengguna berada di direktori "benar" atau tidak.
Stephen C
4

Anda benar-benar perlu melakukan ini dari srcfolder. Di sana Anda mengetikkan baris perintah berikut:

[name of the package].[Class Name] [arguments]

Katakanlah kelas Anda dipanggil CommandLine.class, dan kodenya terlihat seperti ini:

package com.tutorialspoint.java;

    /**
     * Created by mda21185 on 15-6-2016.
     */

    public class CommandLine {
        public static void main(String args[]){
            for(int i=0; i<args.length; i++){
                System.out.println("args[" + i + "]: " + args[i]);
            }
        }
    }

Maka Anda harus cdke folder src dan perintah yang perlu Anda jalankan akan terlihat seperti ini:

java com.tutorialspoint.java.CommandLine this is a command line 200 -100

Dan output pada baris perintah adalah:

args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100
Mike. D
sumber
2
Kelas tidak bisa disebut "CommandLine.class". Itu akan menjadi kesalahan sintaksis Java. (Yang Anda maksud adalah bahwa file yang berisi kelas yang dikompilasi disebut "CommandLine.class" ...). Masalah lainnya adalah bahwa instruksi Anda untuk "cd ke direktori sumber" hanya berfungsi jika Anda mengkompilasi kode >> ke dalam << pohon direktori sumber. Akhirnya, jika kompilasi Anda menggunakan argumen "-cp", maka Anda memerlukan yang setara pada saat Anda menjalankan.
Stephen C
Dalam proyek saya, saya memiliki folder src dan folder bin di root. Saya harus cdmasuk srcdan kemudian menjalankan perintah java ../bin com.blah.blah.MyClassyang bekerja untuk saya. Jadi terima kasih atas tipnya!
tamj0rd2
3

Di Jawa, ketika Anda kadang-kadang menjalankan JVM dari baris perintah menggunakan executable java dan mencoba untuk memulai program dari file kelas dengan public static void main (PSVM), Anda mungkin mengalami kesalahan di bawah ini meskipun parameter classpath ke JVM akurat dan file kelas ada di classpath:

Error: main class not found or loaded

Ini terjadi jika file kelas dengan PSVM tidak dapat dimuat. Salah satu alasan yang mungkin untuk itu adalah bahwa kelas dapat mengimplementasikan antarmuka atau memperluas kelas lain yang tidak ada di classpath. Biasanya jika kelas tidak ada di classpath, kesalahan yang dilemparkan menunjukkan seperti itu. Tetapi, jika kelas yang digunakan diperluas atau diimplementasikan, java tidak dapat memuat kelas itu sendiri.

Referensi: https://www.computingnotes.net/java/error-main-class-not-found-or-loaded/

Anandaraja Ravi
sumber
1
Apakah Anda membaca jawaban yang diterima? Apakah jawaban Anda menambahkan sesuatu yang baru?
Stephen C
1
@StephenC Saya sudah mencoba menemukan alasan dalam daftar Anda dengan melihat kategori "Alasan" dan poin mereka. Saya tidak dapat menemukan titik yang cocok dalam judul "Alasan # 1" dan "Alasan # 2" tidak terlihat dekat dengan kasus saya (karena saya yakin tidak ada masalah dengan classpath itu sendiri). Saya telah menemukan alasannya dengan melakukan percobaan dan saya terkejut bahwa dalam kasus saya, "kelas utama tidak ditemukan" kesalahan ditampilkan karena mengimplementasikan antarmuka tidak di jalur kelas. Tentu Anda dapat mengatakan "Anda harus membaca semua yang dijelaskan dalam posting" tetapi menurut saya daftar alasan Anda dapat ditingkatkan.
Gumkins
3

Ketika menjalankan javadengan -cppilihan seperti yang diiklankan di Windows PowerShell Anda mungkin mendapatkan error yang terlihat sesuatu seperti:

The term `ClassName` is not recognized as the name of a cmdlet, function, script ...

Agar PowerShell menerima perintah, argumen -cpopsi harus terkandung dalam tanda kutip seperti pada:

java -cp 'someDependency.jar;.' ClassName

Membentuk perintah dengan cara ini harus memungkinkan Java memproses argumen classpath dengan benar.

Chezzwizz
sumber
3

Saya juga menghadapi kesalahan serupa saat menguji koneksi Java MongoDB JDBC. Saya pikir itu baik untuk merangkum solusi terakhir saya secara singkat sehingga di masa depan siapa pun dapat langsung melihat ke dua perintah dan baik untuk melanjutkan lebih jauh.

Asumsikan Anda berada di direktori di mana file Java dan dependensi eksternal Anda (file JAR) ada.

Menyusun:

javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
  • -cp - argumen classpath; lulus semua file JAR yang tergantung satu per satu
  • * .java - Ini adalah file kelas Java yang memiliki metode utama. sdsd

Lari:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • Harap perhatikan tanda titik dua (Unix) / koma (Windows) setelah semua file JAR dependensi berakhir
  • Pada akhirnya, amati nama kelas utama tanpa ekstensi apa pun (tidak .class atau .java)
khichar.anil
sumber
Ini semua menganggap bahwa 1) JavaMongoDBConnectiontidak memiliki paket, dan 2) Anda tidak mengubah direktori. Singkatnya, ini rapuh. Dan dengan tidak menjelaskan masalah, itu akan mengarahkan pemula untuk mencoba pendekatan ini dalam situasi di mana itu tidak akan berhasil . Singkatnya, ini mendorong "teknik pemrograman voodoo": en.wikipedia.org/wiki/Voodoo_programming
Stephen C
3

Baiklah, sudah ada banyak jawaban, tetapi tidak ada yang menyebutkan kasus di mana izin file dapat menjadi biang keladinya.

Saat berjalan, pengguna mungkin tidak memiliki akses ke file JAR atau salah satu direktori path. Sebagai contoh, pertimbangkan:

File jar /dir1/dir2/dir3/myjar.jar

User1 yang memiliki file JAR dapat melakukan:

# Running as User1
cd /dir1/dir2/dir3/
chmod +r myjar.jar

Tapi itu masih tidak berhasil:

# Running as User2
java -cp "/dir1/dir2/dir3:/dir1/dir2/javalibs" MyProgram
Error: Could not find or load main class MyProgram

Ini karena pengguna yang berjalan (User2) tidak memiliki akses ke dir1, dir2, atau javalibs atau dir3. Ini dapat membuat orang gila ketika User1 dapat melihat file, dan dapat mengaksesnya, tetapi kesalahan masih terjadi untuk User2.

biocyberman
sumber
2

Saya mendapatkan kesalahan ini setelah melakukan mvn eclipse:eclipse ini.classpath file sedikit.

Harus mengubah garis masuk .classpathdari

<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>

untuk

<classpathentry kind="src" path="src/main/java" output="target/classes" />
<classpathentry kind="src" path="src/main/resources" excluding="**"  output="target/classes" />
Jaanus
sumber
2

Saya tidak dapat menyelesaikan masalah ini dengan solusi yang dinyatakan di sini (meskipun jawabannya menyatakan, sudah pasti, membersihkan konsep saya). Saya menghadapi masalah ini dua kali dan setiap kali saya mencoba solusi yang berbeda (dalam Eclipse IDE).

  • Pertama, saya menemukan beberapa mainmetode di berbagai kelas proyek saya. Jadi, saya telah menghapus mainmetode dari kelas-kelas berikutnya.
  • Kedua, saya mencoba solusi berikut:
    1. Klik kanan pada direktori proyek utama saya.
    2. Kepala ke sumber lalu bersihkan dan tetap dengan pengaturan default dan pada Selesai. Setelah beberapa tugas latar belakang Anda akan diarahkan ke direktori proyek utama Anda.
    3. Setelah itu saya menutup proyek saya, membukanya kembali, dan boom, saya akhirnya menyelesaikan masalah saya.
Anus Kaleem
sumber
1
Menghapus mainmetode tidak akan memperbaiki masalah. Tidak ada yang salah secara teknis dengan aplikasi yang memiliki banyak titik masuk.
Stephen C