“ ไม่สามารถค้นหาหรือโหลดคลาสหลัก” หมายความว่าอะไร


1370

ปัญหาทั่วไปที่นักพัฒนา Java ใหม่พบคือโปรแกรมของพวกเขาล้มเหลวในการทำงานพร้อมกับข้อความแสดงข้อผิดพลาด: Could not find or load main class ...

สิ่งนี้หมายความว่าอะไรเป็นสาเหตุและคุณควรแก้ไขอย่างไร


37
โปรดทราบว่านี่เป็นคำถาม "ตอบด้วยตนเอง" ที่มีวัตถุประสงค์เพื่อเป็นคำถามอ้างอิงทั่วไปสำหรับผู้ใช้ Java ใหม่ ฉันไม่พบคำถามและคำตอบที่มีอยู่ซึ่งครอบคลุมเรื่องนี้อย่างเพียงพอ (IMO)
สตีเฟ่นซี

คำตอบ:


1230

java <class-name>ไวยากรณ์คำสั่ง

ก่อนอื่นคุณต้องเข้าใจวิธีที่ถูกต้องในการเปิดโปรแกรมโดยใช้คำสั่งjava(หรือjavaw)

ไวยากรณ์ปกติ1คือ:

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

โดยที่<option>เป็นตัวเลือกบรรทัดคำสั่ง (เริ่มต้นด้วยอักขระ "-") <class-name>เป็นชื่อคลาส Java แบบเต็มและ<arg>เป็นอาร์กิวเมนต์บรรทัดคำสั่งโดยพลการที่ส่งผ่านไปยังแอปพลิเคชันของคุณ


1 - มีซินแท็กซ์อื่น ๆ ที่อธิบายไว้ใกล้จะจบคำตอบนี้

ชื่อแบบเต็ม (FQN) สำหรับคลาสนั้นถูกเขียนตามอัตภาพตามที่คุณต้องการในซอร์สโค้ด Java เช่น

    packagename.packagename2.packagename3.ClassName

อย่างไรก็ตามjavaคำสั่งบางเวอร์ชันอนุญาตให้คุณใช้เครื่องหมายทับแทนระยะเวลา เช่น

    packagename/packagename2/packagename3/ClassName

ซึ่ง (สับสน) ดูเหมือนว่าชื่อพา ธ ของไฟล์ แต่ไม่ใช่ชื่อเดียว โปรดทราบว่าชื่อที่ผ่านการรับรองโดยสมบูรณ์เป็นคำศัพท์ Java มาตรฐาน ... ไม่ใช่สิ่งที่ฉันเพิ่งสร้างความสับสนให้คุณ :-)

นี่คือตัวอย่างของสิ่งที่javaคำสั่งควรมีลักษณะ:

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

ด้านบนจะทำให้javaคำสั่งทำดังต่อไปนี้:

  1. ค้นหาcom.acme.example.ListUsersคลาสที่คอมไพล์แล้วของคลาส
  2. โหลดคลาส
  3. ตรวจสอบว่าชั้นมีmainวิธีการที่มีลายเซ็น , ประเภทกลับและปรับเปลี่ยนpublic static void main(String[])ให้โดย (หมายเหตุชื่ออาร์กิวเมนต์ของเมธอดไม่ได้เป็นส่วนหนึ่งของลายเซ็น)
  4. สอบถามวิธีการที่ผ่านมันอาร์กิวเมนต์บรรทัดคำสั่ง ( "เฟร็ด", "โจ", "เบิร์ต") String[]ในฐานะที่เป็น

เหตุผลที่ Java ไม่สามารถหาชั้นเรียนได้

เมื่อคุณได้รับข้อความ "ไม่พบหรือโหลดคลาสหลัก ... " นั่นหมายความว่าขั้นตอนแรกล้มเหลว javaคำสั่งก็ไม่สามารถที่จะหาชั้นเรียน และแน่นอนว่า "... " ในข้อความจะเป็นชื่อคลาสที่มีคุณสมบัติครบถ้วนที่javaต้องการ

เหตุใดจึงไม่สามารถหาชั้นเรียนได้

เหตุผล # 1 - คุณทำผิดพลาดกับอาร์กิวเมนต์ classname

สาเหตุแรกคือคุณอาจระบุชื่อคลาสไม่ถูกต้อง (หรือ ... ชื่อคลาสที่ถูกต้อง แต่อยู่ในรูปแบบที่ไม่ถูกต้อง) เมื่อพิจารณาจากตัวอย่างด้านบนนี่คือวิธีที่ผิดหลายวิธีในการระบุชื่อคลาส:

  • ตัวอย่าง # 1 - ชื่อคลาสแบบง่าย:

    java ListUser

    เมื่อคลาสถูกประกาศในแพ็กเกจเช่นcom.acme.exampleคุณต้องใช้ชื่อคลาสแบบเต็มรวมถึงชื่อแพ็กเกจในjavaคำสั่ง เช่น

    java com.acme.example.ListUser
  • ตัวอย่าง # 2 - ชื่อไฟล์หรือชื่อพา ธ มากกว่าชื่อคลาส:

    java ListUser.class
    java com/acme/example/ListUser.class
  • ตัวอย่าง # 3 - ชื่อคลาสที่ปลอกไม่ถูกต้อง:

    java com.acme.example.listuser
  • ตัวอย่าง # 4 - การพิมพ์ผิด

    java com.acme.example.mistuser
  • ตัวอย่าง # 5 - ชื่อไฟล์ต้นฉบับ (ยกเว้น Java 11 หรือใหม่กว่า; ดูด้านล่าง)

    java ListUser.java
  • ตัวอย่าง # 6 - คุณลืมชื่อคลาสทั้งหมด

    java lots of arguments

เหตุผลที่ # 2 - classpath ของแอปพลิเคชันถูกระบุอย่างไม่ถูกต้อง

สาเหตุที่เป็นไปได้ที่สองคือชื่อคลาสนั้นถูกต้อง แต่javaคำสั่งไม่สามารถหาคลาสได้ เพื่อให้เข้าใจสิ่งนี้คุณต้องเข้าใจแนวคิดของ "classpath" สิ่งนี้อธิบายได้ดีจากเอกสารของ Oracle:

ดังนั้น ... หากคุณระบุชื่อคลาสอย่างถูกต้องสิ่งต่อไปที่ต้องตรวจสอบคือคุณได้ระบุคลาสพา ธ อย่างถูกต้อง:

  1. อ่านเอกสารทั้งสามฉบับที่ลิงก์ด้านบน (ใช่ ... อ่านพวกเขา! มันเป็นสิ่งสำคัญที่โปรแกรมเมอร์ Java เข้าใจอย่างน้อยพื้นฐานของการทำงานของกลไก classpath Java)
  2. ดูบรรทัดคำสั่งและ / หรือตัวแปรสภาพแวดล้อม CLASSPATH ที่มีผลเมื่อคุณรันjavaคำสั่ง ตรวจสอบว่าชื่อไดเร็กทอรีและชื่อไฟล์ JAR ถูกต้อง
  3. หากมีชื่อพา ธสัมพัทธ์ใน classpath ตรวจสอบว่าพวกเขาแก้ไขอย่างถูกต้อง ... จากไดเรกทอรีปัจจุบันที่มีผลเมื่อคุณเรียกใช้javaคำสั่ง
  4. ตรวจสอบว่าคลาส (ที่กล่าวถึงในข้อความแสดงข้อผิดพลาด) สามารถอยู่ในclasspath ที่มีประสิทธิภาพ
  5. โปรดทราบว่าไวยากรณ์ classpath นั้นแตกต่างกันสำหรับ Windows กับ Linux และ Mac OS (ตัวแยก classpath อยู่;บน Windows และ:ที่อื่น ๆ หากคุณใช้ตัวคั่นที่ไม่ถูกต้องสำหรับแพลตฟอร์มของคุณคุณจะไม่ได้รับข้อความแสดงข้อผิดพลาดอย่างชัดเจนแทนคุณจะได้รับไฟล์หรือไดเรกทอรีที่ไม่มีอยู่บนเส้นทางที่จะถูกเพิกเฉยอย่างเงียบ ๆ .)

เหตุผลที่ # 2a - ไดเรกทอรีที่ไม่ถูกต้องอยู่ใน classpath

เมื่อคุณวางไดเรกทอรีบน classpath นั้นจะสอดคล้องกับรูทของพื้นที่ชื่อที่ผ่านการรับรอง เรียนที่จะมีอยู่ในโครงสร้างไดเรกทอรีรากใต้ว่าด้วยการแมปชื่อที่มีคุณสมบัติครบถ้วนที่จะพา ธ ตัวอย่างเช่นหาก "/ usr / local / acme / classes" อยู่ในคลาสพา ธ ดังนั้นเมื่อ JVM ค้นหาคลาสที่เรียกว่าcom.acme.example.Foonไฟล์จะค้นหาไฟล์ ".class" ด้วยชื่อพา ธ นี้:

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

หากคุณใส่ "/ usr / local / acme / classes / com / acme / example" บน classpath ดังนั้น JVM จะไม่สามารถหาชั้นเรียนได้

เหตุผลที่ # 2b - เส้นทางไดเรกทอรีย่อยไม่ตรงกับ FQN

หากคลาส FQN ของคุณเป็นcom.acme.example.Foonเช่นนั้น JVM จะมองหา "Foon.class" ในไดเรกทอรี "com / acme / example":

  • หากโครงสร้างไดเรกทอรีของคุณไม่ตรงกับการตั้งชื่อแพ็คเกจตามรูปแบบด้านบน JVM จะไม่พบชั้นเรียนของคุณ

  • หากคุณพยายามเปลี่ยนชื่อคลาสโดยการย้ายคลาสนั้นจะล้มเหลวเช่นกัน ... แต่สแต็กข้อยกเว้นสแต็กจะแตกต่างกัน มีแนวโน้มที่จะพูดบางสิ่งเช่นนี้:

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

    เนื่องจาก FQN ในไฟล์คลาสไม่ตรงกับสิ่งที่ class loader ต้องการที่จะค้นหา

หากต้องการยกตัวอย่างที่เป็นรูปธรรมสมมติว่า:

  • คุณต้องการเรียกใช้com.acme.example.Foonคลาส
  • เส้นทางของไฟล์เต็ม/usr/local/acme/classes/com/acme/example/Foon.class,
  • ไดเรกทอรีที่ทำงานปัจจุบันของคุณ/usr/local/acme/classes/com/acme/example/,

แล้ว:

# 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

หมายเหตุ:

  • -classpathตัวเลือกที่สามารถลงไป-cpในส่วนเผยแพร่ Java ตรวจสอบรายการคู่มือที่เกี่ยวข้องสำหรับjava, javacและอื่น ๆ
  • คิดอย่างรอบคอบเมื่อเลือกระหว่างชื่อพา ธ สัมบูรณ์และสัมพัทธ์ในพา ธ คลาส จำไว้ว่าชื่อพา ธ สัมพัทธ์อาจ "หยุด" หากไดเรกทอรีปัจจุบันเปลี่ยนไป

เหตุผล # 2c - การพึ่งพาที่ขาดหายไปจาก classpath

คลาสพา ธ ต้องรวมคลาสอื่น ๆ (ที่ไม่ใช่ระบบ) ทั้งหมดที่แอปพลิเคชันของคุณขึ้นอยู่กับ (คลาสของระบบจะอยู่โดยอัตโนมัติและคุณไม่ต้องกังวลกับสิ่งนี้) สำหรับคลาสหลักที่จะโหลดอย่างถูกต้อง JVM ต้องค้นหา:

(หมายเหตุ: ข้อกำหนด JLS และ JVM อนุญาตให้มีขอบเขตสำหรับ JVM ในการโหลดคลาส "lazily" และสิ่งนี้อาจส่งผลต่อเมื่อมีข้อยกเว้นตัวโหลดคลาส)

เหตุผลที่ # 3 - คลาสถูกประกาศในแพ็กเกจที่ไม่ถูกต้อง

บางครั้งมันเกิดขึ้นที่มีคนใส่ไฟล์ซอร์สโค้ดลงในโฟลเดอร์ที่ไม่ถูกต้องในทรีซอร์สโค้ดของพวกเขาหรือพวกเขาไม่ออกpackageประกาศ หากคุณทำสิ่งนี้ใน IDE คอมไพเลอร์ของ IDE จะบอกคุณเกี่ยวกับสิ่งนี้ทันที ในทำนองเดียวกันถ้าคุณใช้เครื่องมือสร้าง Java ที่เหมาะสมเครื่องมือจะทำงานjavacในลักษณะที่จะตรวจพบปัญหา อย่างไรก็ตามหากคุณสร้างโค้ด Java ด้วยตัวเองคุณสามารถทำได้ในลักษณะที่คอมไพเลอร์ไม่สังเกตเห็นปัญหาและไฟล์ ".class" ที่ได้นั้นไม่ได้อยู่ในตำแหน่งที่คุณคาดหวัง

หากยังหาปัญหาไม่พบ

มีหลายสิ่งหลายอย่างให้ตรวจสอบและง่ายต่อการพลาดบางสิ่ง ลองเพิ่ม-Xdiagตัวเลือกในjavaบรรทัดคำสั่ง (เป็นสิ่งแรกหลังจากนั้นjava) มันจะเอาท์พุทสิ่งต่าง ๆ เกี่ยวกับการโหลดคลาสและสิ่งนี้อาจให้เบาะแสว่าปัญหาจริงคืออะไร

และพิจารณาปัญหาที่อาจเกิดขึ้นจากการคัดลอกและวางอักขระที่มองไม่เห็นหรือไม่ใช่ ASCII จากเว็บไซต์เอกสารและอื่น ๆ และพิจารณาว่า "homoglyphs" เป็นตัวอักษรหรือสัญลักษณ์สองตัวที่ดูเหมือนกัน ... แต่ไม่ใช่

สุดท้ายคุณก็สามารถเรียกใช้เห็นได้ชัดว่าเป็นปัญหานี้ถ้าคุณพยายามที่จะเปิดตัวจากไฟล์ JAR (META-INF/*.SF)ที่มีลายเซ็นไม่ถูกต้องใน


ไวยากรณ์ทางเลือกสำหรับ java

java commandมีสามไวยากรณ์ทางเลือกสำหรับการเปิดตัวโปรแกรมจาวาโดยใช้เป็น

1) ไวยากรณ์ที่ใช้สำหรับเรียกใช้งานไฟล์ "executable" JAR มีดังนี้:

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

เช่น

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

ชื่อของคลาส entry-point (เช่นcom.acme.example.ListUser) และ classpath ถูกระบุใน MANIFEST ของไฟล์ JAR

2) ไวยากรณ์สำหรับเรียกใช้แอปพลิเคชันจากโมดูล (Java 9 และใหม่กว่า) มีดังนี้:

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

ชื่อของคลาสจุดเข้าใช้งานที่มีการกำหนดไว้อย่างใดอย่างหนึ่งโดยตัวของมันเองหรือจะได้รับโดยไม่จำเป็น<module><mainclass>

3) จาก Java 11 เป็นต้นไปคุณสามารถรวบรวมและเรียกใช้ไฟล์ซอร์สโค้ดเดียวและรันด้วยไวยากรณ์ต่อไปนี้:

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

โดยที่ (ปกติ) ไฟล์ที่มีคำต่อท้าย ".java"

สำหรับรายละเอียดเพิ่มเติมโปรดดูเอกสารประกอบอย่างเป็นทางการสำหรับjavaคำสั่งสำหรับรุ่น Java ที่คุณใช้


IDEs

Java IDE ทั่วไปมีการสนับสนุนสำหรับการรันแอปพลิเคชัน Java ใน IDE JVM เองหรือในลูก JVM สิ่งเหล่านี้โดยทั่วไปจะยกเว้นจากข้อยกเว้นนี้เนื่องจาก IDE ใช้กลไกของตนเองเพื่อสร้าง runtime classpath ระบุคลาสหลักและสร้างjavaบรรทัดคำสั่ง

อย่างไรก็ตามยังคงเป็นไปได้ที่ข้อยกเว้นนี้จะเกิดขึ้นหากคุณทำสิ่งต่าง ๆ ที่อยู่ด้านหลังของ IDE ตัวอย่างเช่นหากก่อนหน้านี้คุณตั้งค่าตัวเรียกใช้งานแอปพลิเคชันสำหรับแอป Java ของคุณใน Eclipse และจากนั้นคุณย้ายไฟล์ JAR ที่มีคลาส "หลัก" ไปยังตำแหน่งอื่นในระบบไฟล์โดยไม่บอก Eclipse Eclipse จะเปิด JVM โดยไม่เจตนา ด้วย classpath ที่ไม่ถูกต้อง

ในระยะสั้นหากคุณพบปัญหานี้ใน IDE ให้ตรวจสอบสิ่งต่าง ๆ เช่นสถานะ IDE เก่าการอ้างอิงโครงการที่เสียหายหรือการกำหนดค่าตัวเรียกใช้งานที่เสียหาย

นอกจากนี้ยังเป็นไปได้ที่ IDE จะสับสน IDE เป็นชิ้นส่วนซอฟต์แวร์ที่มีความซับซ้อนอย่างมากซึ่งประกอบไปด้วยส่วนที่มีปฏิสัมพันธ์มากมาย หลายส่วนเหล่านี้นำกลยุทธ์การแคชต่าง ๆ มาใช้เพื่อทำให้ IDE เป็นแบบตอบสนองโดยรวม บางครั้งสิ่งเหล่านี้อาจผิดไปได้และอาการหนึ่งที่เป็นไปได้คือปัญหาเมื่อเปิดแอปพลิเคชัน หากคุณสงสัยว่าอาจเกิดเหตุการณ์เช่นนี้ขึ้นคุณควรลองทำสิ่งอื่นเช่นเริ่มต้น IDE ของคุณสร้างโครงการใหม่และอื่น ๆ


การอ้างอิงอื่น ๆ


43
ฉันมีปัญหานี้เมื่อฉันพยายามเรียกใช้ Class ด้วยห้องสมุดของ บริษัท อื่น ฉันเรียก java เช่นนี้: java -cp ../third-party-library.jar com.my.package.MyClass; มันใช้งานไม่ได้ แต่จำเป็นต้องเพิ่มโฟลเดอร์ในเครื่องไปยังเส้นทางของคลาสด้วย (คั่นด้วย:ดังนี้: java -cp ../third-party-library.jar:. com.my.package.MyClassจากนั้นควรทำงาน
lanoxx

23
หลังจากหลายปีของการเขียนโปรแกรมจาวาฉันยังคงสามารถจบในหน้านี้ได้ สำหรับผมปัญหาคือการที่ไวยากรณ์ classpath เป็น OS ฉันเป็นคนใหม่ในการเขียนโปรแกรมบน Windows และไม่มีความคิด
keyser

5
หมายเหตุเพิ่มเติมจุดที่ 2 ช่วยฉันด้วย! เป็นเรื่องน่าเศร้าที่เห็นjavaว่าไม่ได้บอกว่ามันไม่พบคลาสที่อิมพอร์ต แต่แทนที่จะเป็นคลาสหลักที่คุณพยายามรัน นี่คือการเข้าใจผิดแม้ว่าฉันแน่ใจว่ามีเหตุผลสำหรับสิ่งนั้น ฉันมีกรณีที่javaรู้แน่ชัดว่าชั้นเรียนของฉันอยู่ที่ไหน แต่ไม่พบชั้นเรียนที่นำเข้า แทนที่จะบอกว่ามันบ่นเกี่ยวกับการไม่หาชั้นเรียนหลักของฉัน จริงๆแล้ว annoing
MSX

ฉันมีปัญหานี้สองครั้งใน Eclipse ครั้งแรกที่ลายเซ็นของ main () ผิด ครั้งที่สองที่ฉันเปลี่ยนชื่อเป็น. jar และแม้ว่าฉันจะเพิ่มอันใหม่ลงในเส้นทางการสร้าง Eclipse ไม่พบสิ่งเก่าดังนั้นโครงการจึงไม่คอมไพล์ด้วยข้อผิดพลาดนี้ ฉันต้องลบไฟล์. jar ออกจากโครงการ> คุณสมบัติ> เส้นทาง Java Build> ไลบรารี
GregT

ฉันพบมันครั้งที่สาม ฉันเรียกใช้โปรแกรมจากไฟล์แบตช์ Windows 10 และใส่ชื่อ. jar ในตัวแปร (เรียกว่า "-cp% jarname%; lib *") ฉันวางที่ว่างเพิ่มเติมไว้ที่ส่วนท้ายของชื่อผิดและมันทำให้เกิดข้อผิดพลาด Hat trick :)
GregT

239

หากชื่อรหัสต้นฉบับของคุณเป็น HelloWorld.java, HelloWorld.classรหัสเรียบเรียงของคุณจะ

คุณจะได้รับข้อผิดพลาดนั้นหากคุณโทรหาโดยใช้:

java HelloWorld.class

ใช้สิ่งนี้แทน:

java HelloWorld

3
ปัญหาคือโซลูชันนี้ใช้ได้กับคลาส Java ที่ประกาศในแพ็คเกจเริ่มต้นเท่านั้นโดยไม่มีการขึ้นต่อกันของไฟล์ JAR (และถึงแม้จะไม่ใช่ทุกครั้ง) โปรแกรม Java ส่วนใหญ่นั้นไม่ง่ายอย่างนั้น
สตีเฟ่นซี

1
เช่นเดียวกับสตีเฟ่นกล่าวว่าสิ่งนี้ใช้ได้กับ "แพ็คเกจเริ่มต้น" เท่านั้น - ซึ่งหมายความว่าไม่มีการประกาศแพ็คเกจที่ด้านบนของไฟล์ สำหรับการทดสอบรหัสบางอย่างฉันได้: javac TestCode.javaตามด้วยjava TestCode
บางคน

สิ่งนี้ไม่ได้ผลสำหรับฉัน มันยังบอกว่า "ไม่สามารถหาหรือโหลด HelloWorld ระดับหลัก"
จิม

java -jar HelloWorld.jar เป็นตัวเลือกด้วย
BMaximus

12
ฉันต้องทำ java -classpath . HelloWorld
คริสเจ้าชาย

136

หากคลาสของคุณอยู่ในแพ็คเกจคุณต้องไปcdยังไดเรกทอรีรูทของโครงการของคุณและรันโดยใช้ชื่อที่ผ่านการรับรองโดยสมบูรณ์ของคลาส (packageName.MainClassName)

ตัวอย่าง:

ชั้นเรียนของฉันอยู่ที่นี่:

D:\project\com\cse\

ชื่อเต็มของคลาสหลักของฉันคือ:

com.cse.Main

ดังนั้นฉันcdกลับไปที่ไดเรกทอรีโครงการราก:

D:\project

จากนั้นออกjavaคำสั่ง:

java com.cse.Main

คำตอบนี้ใช้สำหรับการช่วยเหลือโปรแกรมเมอร์ Java มือใหม่จากความขัดข้องที่เกิดจากข้อผิดพลาดทั่วไปผมแนะนำให้คุณอ่านคำตอบที่ได้รับการยอมรับสำหรับความรู้เชิงลึกเกี่ยวกับ java classpath


2
คำตอบนี้ทำให้สมมติฐานทั้งหมดโหลด และมีวิธีอื่นในการบรรลุเป้าหมายนี้ แทนที่จะทำตามคำแนะนำข้างต้นโดยสุ่มสี่สุ่มห้าฉันอยากจะแนะนำให้ผู้คนใช้เวลาอ่านลิงค์ในคำตอบของฉันซึ่งอธิบายว่า Java classpath ทำงานอย่างไร ดีกว่าที่จะเข้าใจสิ่งที่คุณกำลังทำ ...
สตีเฟนซี

2
คำตอบนี้ทำให้สมมติฐานที่แน่นอนที่ฉันต้องการ :) ฉันอยู่ในไดเรกทอรีของไฟล์. class และ java.exe ไม่ทำงาน เมื่อฉัน cd-ed ด้านบนและวิ่งด้วยชื่อแพคเกจรวมอยู่ในบรรทัดคำสั่งมันใช้งานได้
Nick Constantine

61

หากคุณกำหนดคลาสหลักและเมธอดหลักใน apackage , คุณควรรันบนไดเรคทอรีลำดับชั้นโดยใช้ชื่อเต็มของคลาส (packageName.MainClassName )

สมมติว่ามีไฟล์ซอร์สโค้ด (Main.java):

package com.test;

public class Main {

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

สำหรับการเรียกใช้รหัสนี้คุณควรวางในแพคเกจเช่นไดเรกทอรีMain.Class ./com/test/Main.Javaและในการใช้ไดเรกทอรีรูjava com.test.Main


1
ดู "หมายเหตุเพิ่มเติม # 1" ของคำตอบของฉัน สำหรับคำอธิบายที่ดีขึ้นของปัญหานี้
สตีเฟนซี

14
@StephenC ใช่คำตอบของคุณสมบูรณ์กว่า (และแน่นอน +1) แต่คำตอบนี้มีคำว่า "package" อยู่ในนั้นซึ่งทำให้ฉันสามารถค้นหาสิ่งที่ฉันต้องการได้อย่างรวดเร็ว และมันก็ใช้งานได้ ดังนั้น +1 Razavi StephenC คุณขาดตัวอย่างแพ็คเกจง่ายๆที่ฉันต้องการเพราะฉันใหม่กับ Java
kmort

5
นี่เป็นปัญหาของฉันอย่างแน่นอน ฉันได้อ่านเอกสาร Java จำนวนมากและตัวอย่างที่เป็นรูปธรรมนี้คือสิ่งที่ฉันต้องการ
John

1
ใช่ตัวอย่างที่เป็นรูปธรรมเป็นสิ่งที่ดี ฉันแน่ใจว่าคำตอบหลักนั้นละเอียดมาก แต่ก็ยากที่จะเห็นต้นไม้ในป่า Nice one @Razavi
Pixel

1
ฉันชอบคำตอบที่สั้นและมีประโยชน์แทนคำตอบที่ยอมรับ!
Spara

46

เมื่อรหัสเดียวกันทำงานบนพีซีเครื่องหนึ่ง แต่มันแสดงข้อผิดพลาดในอีกวิธีที่ดีที่สุดที่ฉันเคยพบคือการรวบรวมดังต่อไปนี้:

javac HelloWorld.java
java -cp . HelloWorld

2
นี่ไม่ใช่คำแนะนำที่ดี คุณขึ้นอยู่กับตัวแปรสภาพแวดล้อม CLASSPATH ที่ไม่ได้ตั้งค่าหรือมีค่าที่สอดคล้องกับ "." ใช่มันใช้งานได้ในหลายกรณี แต่มันจะไม่ทำงานในที่อื่น ๆ
Stephen C

ก็javac -classpath . HelloWorld.javaคงจะทำงานได้ดีอย่างแน่นอน! และนั่นเป็นทางออกที่ดีกว่าในกรณีของคุณ
สตีเฟ่นซี

2
หากคุณมี 'package com.some.address' เป็นบรรทัดแรก - สิ่งนี้จะไม่ทำงาน คุณจะต้องแสดงความคิดเห็น 'ที่อยู่แพ็คเกจ' ..
Joe

1
@ Joe - แฮ็คนั้น (แสดงความคิดเห็นในแพ็คเกจ) จะใช้งานได้ (ในบางกรณี) แต่มันเป็นความคิดที่ไม่ดี แนวคิดที่ดีกว่าคือการเรียนรู้ / ทำความเข้าใจกับสิ่งที่ทำให้เกิดปัญหาและใช้วิธีแก้ไขปัญหาที่ถูกต้อง
สตีเฟ่นซี

36

สิ่งที่ช่วยฉันได้ระบุ classpath ในบรรทัดคำสั่งตัวอย่างเช่น:

  1. สร้างโฟลเดอร์ใหม่ C:\temp

  2. สร้างไฟล์ Temp.java C:\tempด้วยคลาสต่อไปนี้:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
  3. เปิดบรรทัดคำสั่งในโฟลเดอร์C:\tempและเขียนคำสั่งต่อไปนี้เพื่อคอมไพล์คลาส Temp:

    javac Temp.java
  4. รันคลาส Java ที่คอมไพล์แล้วเพิ่ม-classpathตัวเลือกเพื่อให้ JRE ทราบตำแหน่งที่จะหาคลาส:

    java -classpath C:\temp Temp Hello!

3
ใน Ubuntu ฉันต้องระบุเส้นทาง ไม่เข้าใจว่าเหตุใดจึงไม่สามารถใช้ไดเรกทอรีการทำงานปัจจุบันได้ตามค่าเริ่มต้น ฉันเชื่อว่า Java ได้รับการสนับสนุนจากผู้ผลิตคีย์บอร์ด !!
ไป

1
@gone - เหตุผลที่ "." ไม่ได้อยู่ใน $ PATH โดยค่าเริ่มต้นคือมันเป็นกับดักความปลอดภัย seas.upenn.edu/cets/answers/dot-path.html
Stephen C

ขอบคุณมากสำหรับสิ่งนี้ ...... แม้ว่าจะไม่แน่ใจว่าทำไม java ไม่สามารถค้นหา classpath ได้แม้หลังจากตั้งค่าในตัวแปรสภาพแวดล้อม
akash89

@ akash89 - สาเหตุที่เป็นไปได้มากที่สุดคือ: 1) javaไม่ได้ดู $ CLASSPATH (เพราะคุณใช้ -classpath หรือ -jar) หรือ 2) การตั้งค่า classpath ไม่ได้ตั้งค่าในสภาพแวดล้อมที่ไม่ได้มีผลบังคับใช้ในบริบทที่javaเป็น วิ่ง; เช่นเนื่องจากคุณไม่ได้ "ซอร์ส" ไฟล์ที่เพิ่มคำสั่ง setenv ในเชลล์ด้านขวา
Stephen C

ฉันยังคงมีข้อผิดพลาด: ไม่สามารถค้นหาหรือโหลด Temp class หลักได้ทุกคนสามารถช่วยได้!
สตาร์

27

ตามข้อความแสดงข้อผิดพลาด ("ไม่พบหรือโหลดคลาสหลัก") มีปัญหาสองประเภท:

  1. ไม่พบคลาสหลัก
  2. ไม่สามารถโหลดคลาสหลัก(กรณีนี้ไม่ได้กล่าวถึงทั้งหมดในคำตอบที่ยอมรับ)

ไม่พบคลาสหลักเมื่อมีการพิมพ์ผิดหรือไวยากรณ์ผิดในชื่อคลาสที่ผ่านการรับรองโดยสมบูรณ์หรือไม่มีอยู่ใน classpath ที่ระบุ

ไม่สามารถโหลดคลาสหลักได้เมื่อไม่สามารถเริ่มคลาสได้โดยทั่วไปคลาสหลักจะขยายคลาสอื่นและคลาสนั้นไม่มีอยู่ใน classpath ที่ระบุ

ตัวอย่างเช่น:

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

หากไม่มีอูฐสปริงข้อผิดพลาดนี้จะถูกรายงาน


"พื้นฐาน" มีหมวดหมู่อื่นอีกมากมายเช่นกัน และปัญหาของซูเปอร์คลาสที่หายไปนั้นเป็นเรื่องย่อยที่ผิดปกติมาก (แปลกมากจนฉันไม่เคยเห็นมัน ... ในคำถามที่ถามในเว็บไซต์นี้)
สตีเฟ่นซี

มีสองเนื่องจากข้อผิดพลาดระบุว่า "ไม่สามารถค้นหาหรือโหลดคลาสหลัก" หากมีหมวดหมู่อื่นโปรดแจ้งฉัน ฉันเคยเห็นแล้วดังนั้นต้องการแบ่งปันที่นี่บางทีคนอื่นจะต้องการมัน
Xiao Peng - ZenUML.com

1
ฉันจะแก้ไขเป็นบางอย่างเช่น "คุณต้องรวมคลาสทั้งหมดที่จำเป็นในการเริ่มต้นคลาสหลักเพื่อหลีกเลี่ยงข้อผิดพลาดนี้โดยเฉพาะ" ฉันไม่ได้พยายามโน้มน้าวคุณ มันเป็นวิธีที่ฉันต้องการจะดู ฉันทิ้งคำตอบไว้ที่นี่สำหรับคนที่อาจชอบอ่านสิ่งต่าง ๆ ด้วยวิธีนี้ อย่าขยายการสนทนานี้อีกต่อไป :) ฉันเปลี่ยนคำกล่าวของฉันเป็น "ไม่ได้กล่าวถึงในคำตอบที่ยอมรับ" และหวังว่าคุณจะรู้สึกดีขึ้น
Xiao Peng - ZenUML.com

5
ข้อมูลนี้มีความสำคัญและควรกล่าวถึงอย่างชัดเจน (นี่เป็นคำตอบเดียวที่กล่าวถึงextends) ฉันเพิ่งเรียนรู้วิธีที่ยากที่เมื่อคลาสหลักล้มเหลวในการโหลดเพราะมันขยายออกไปอีกอันที่ไม่สามารถพบได้จาวาไม่ได้รายงานว่าไม่พบคลาสจริง (ไม่เหมือนNoClassDefFoundError) ใช่มันเกิดขึ้นและมันเป็นสถานการณ์ที่ดึงผมเมื่อคุณไม่รู้เรื่องนี้
Hugues M.

1
ในสถานการณ์นี้มีวิธีใดที่จะบอกได้อย่างชัดเจนว่าคลาสการพึ่งพาใดที่ไม่สามารถโหลดได้
Carlos A. Ibarra

16

ฉันมีข้อผิดพลาดดังกล่าวในกรณีนี้:

java -cp lib.jar com.mypackage.Main

ใช้งานได้กับ;Windows และ:Unix:

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

ใช่. อาจเป็นเพราะคุณMainไม่ได้อยู่ในไฟล์ JAR -cp lib.jar;หมายถึงสิ่งเดียวกัน-cp lib.jar;. เช่นไดเรกทอรีปัจจุบันรวมอยู่ใน classpath
Stephen C

ในที่สุดก็แก้ไขปัญหาสำหรับยูนิกซ์ .. ขอบคุณ (ทำงานร่วมกับ :)
Vicky

16

ลอง-Xdiag

คำตอบของ Steve Cครอบคลุมกรณีที่เป็นไปได้อย่างดี แต่บางครั้งเพื่อตรวจสอบว่าไม่พบคลาสหรือโหลดอาจไม่ง่ายขนาดนั้น ใช้java -Xdiag(ตั้งแต่ JDK 7) วิธีนี้จะพิมพ์ stacktrace ที่สวยงามซึ่งให้คำแนะนำเกี่ยวกับความCould not find or load main classหมายของข้อความ

ตัวอย่างเช่นมันสามารถชี้ให้คุณไปที่คลาสอื่น ๆ ที่ใช้โดยคลาสหลักที่ไม่พบและป้องกันไม่ให้โหลดคลาสหลัก


16

ใช้คำสั่งนี้:

java -cp . [PACKAGE.]CLASSNAME

ตัวอย่าง: หากชื่อคลาสของคุณคือ Hello.class สร้างขึ้นจาก Hello.java ให้ใช้คำสั่งด้านล่าง:

java -cp . Hello

หากไฟล์ Hello.java ของคุณอยู่ใน package com.demo ให้ใช้คำสั่งด้านล่าง

java -cp . com.demo.Hello

ด้วย JDK 8 หลายครั้งมันเกิดขึ้นว่าไฟล์คลาสมีอยู่ในโฟลเดอร์เดียวกัน แต่javaคำสั่งคาดว่า classpath และด้วยเหตุนี้เราเพิ่ม-cp .เพื่อใช้โฟลเดอร์ปัจจุบันเป็นการอ้างอิงสำหรับ classpath


ใช้งานได้ในกรณีง่าย ๆ เท่านั้น กรณีที่ซับซ้อนมากขึ้นต้องใช้ classpath ที่ซับซ้อนมากขึ้น
สตีเฟ่นซี

และสำหรับ >> << กรณีง่าย ๆ-cp .ไม่จำเป็นเพราะถ้า$CLASSPATHไม่มีการตั้ง.ค่า classpath นั้นจะเป็นค่าเริ่มต้น
สตีเฟ่นซี

ไม่มีสตีเฟ่นหลายครั้งในคลาสพา ธ เริ่มต้นของ Windows ไม่ทำงาน ฉันลองใช้เครื่องจักรที่แตกต่างกันสามเครื่องคุณสามารถลองใช้ได้เช่นกัน
Shailu

อาจเป็นเพราะคุณได้ตั้งค่าตัวแปรสภาพแวดล้อม% CLASSPATH% จริง หากคุณทำเช่นนั้นแสดงว่าคุณไม่ได้ใช้ classpath เริ่มต้น ( echo %CLASSPATH%ผลลัพธ์คืออะไร) และไม่ฉันไม่สามารถตรวจสอบได้เพราะฉันไม่มีพีซี Windows
สตีเฟนซี

2
สิ่งนี้ใช้ได้สำหรับฉันเมื่อฉันพยายามเรียกใช้โปรแกรมอย่างง่ายจากบรรทัดคำสั่ง
SnuKies

15

บางครั้งสิ่งที่อาจทำให้เกิดปัญหาไม่มีอะไรเกี่ยวข้องกับชั้นเรียนหลักและฉันต้องค้นหาวิธีที่ยาก มันเป็นห้องสมุดอ้างอิงที่ฉันย้ายและมันทำให้ฉัน:

ไม่สามารถค้นหาหรือโหลดคลาสหลัก xxx Linux

ฉันเพิ่งลบการอ้างอิงนั้นเพิ่มอีกครั้งและมันก็ใช้ได้ดีอีกครั้ง


1
ดูเหมือนว่าปัญหาคือคุณมี classpath ที่ไม่ถูกต้องเนื่องจาก "การอ้างอิง" ที่เสียหายในโครงการของคุณใน IDE ของคุณ ฉันจะอัปเดตคำตอบของฉันให้ครอบคลุมกรณีนั้น
Stephen C

@StephenC และ EduardoDennis มันเป็นที่นี่ด้วยมีขวดที่ขาดหายไป jar นั้นมีส่วนต่อประสานที่ชั้นหลักขึ้นอยู่กับการสร้างอินสแตนซ์ ดังนั้นข้อความแสดงข้อผิดพลาดกว้างเกินไป ฉันควรจะพูดว่า "ไม่พบ" ถ้าไม่พบไฟล์คลาสและ "ไม่สามารถโหลด (ขาดการอ้างอิง)" หากมีสิ่งอื่นที่ขาดหายไป แต่ไม่ใช่ตัวไฟล์เองดังนั้นข้อความแสดงข้อผิดพลาดที่กว้างเกินไปจะทำให้เข้าใจผิด ในส่วน "find" ของมัน :(
Aquarius Power

@AquariusPower - ควรมีสแต็ค "ที่เกิดจาก" เพิ่มเติมสำหรับข้อยกเว้น "สาเหตุ" ที่กล่าวว่าคลาสที่หายไป หากคุณต้องการที่จะแนะนำให้นักพัฒนา Java ที่พวกเขาเปลี่ยนข้อผิดพลาดที่ได้รับการบอกว่ามานานกว่า 20 ปี ... รู้สึกฟรี (ฉันคิดว่าข้อความแสดงข้อผิดพลาดนั้นถูกต้องปัญหาก็คือ >> คุณ << จำกัด ขอบเขตของคำผิดให้แคบลง)
สตีเฟ่นซี

@StephenC สิ่งที่ฉันหมายถึงคือพวกเขามีสิทธิ์เข้าถึงข้อมูลหากไฟล์คลาสหลักพร้อมใช้งานหรือไม่ดังนั้นทำไมไม่แสดงข้อความข้อผิดพลาดที่ดีกว่าให้เราบอกว่าไฟล์ดังกล่าวหายไป ในทางกลับกันพวกเขาอาจพูดว่า "พบไฟล์ แต่ไม่สามารถโหลดได้" ในตอนนั้นเราจะมุ่งเน้นไปที่การพึ่งพาโดยทันทีแทนที่จะเสียเวลาค้นคว้าและทดสอบสิ่งต่าง ๆ ให้เข้าใจครึ่งวัน แค่นั้นฉันหมายถึง :) พวกเขาอาจทำได้ในเวลา จำกัด มากกว่า 20 ปี แต่พวกเขาสามารถปรับปรุงได้และเราอยู่ที่นี่เพื่อให้สิทธิ์ที่จะเกิดขึ้นผ่านการวิจารณ์และการร้องเรียนของเรา! : D
กุมภ์

โปรดเข้าใจว่า >> ฉันหมายถึงอะไร << การร้องเรียนเกี่ยวกับมันในความคิดเห็นที่คลุมเครือในคำถามและคำตอบอายุ 3 ปีจะไม่ประสบความสำเร็จ คนที่อาจทำเรื่องร้องเรียนอย่างจริงจังจะไม่สังเกตเห็น หากคุณต้องการทำสิ่งที่สร้างสรรค์ให้ส่งปะ (ฉันไม่ให้คะแนนโอกาสของคุณ แต่พวกเขาจะยิ่งใหญ่กว่าถ้าคุณเพียงแค่คร่ำครวญเกี่ยวกับเรื่องนี้)
สตีเฟ่นซี

10

ในตัวอย่างนี้คุณมี:

ไม่พบหรือโหลดระดับหลัก? classpath

เป็นเพราะคุณกำลังใช้ "-classpath" แต่เส้นประไม่ใช่เส้นประเดียวกับที่ใช้javaบนพรอมต์คำสั่ง ฉันมีปัญหาในการคัดลอกและวางจากNotepadเป็น cmd


2
ว้าว! นั่นเป็นสาเหตุที่แปลกประหลาดอย่างสิ้นเชิง! ( แต่มันจะทำหน้าที่คุณที่เหมาะสมสำหรับการใช้แผ่นจดบันทึกแทนโปรแกรมแก้ไขข้อความจริง :-))
สตีเฟ่น C

10

ฉันมีปัญหาเดียวกันและในที่สุดก็พบข้อผิดพลาดของฉัน :) ฉันใช้คำสั่งนี้เพื่อรวบรวมและทำงานได้อย่างถูกต้อง:

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

แต่คำสั่งนี้ใช้ไม่ได้สำหรับฉัน (ฉันหาหรือโหลดคลาสหลักไม่ได้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

ในที่สุดฉันเพิ่งเพิ่มอักขระ ':' ที่ส่วนท้ายของ classpath และปัญหาได้รับการแก้ไขแล้ว:

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

7

ในกรณีของฉันเกิดข้อผิดพลาดเนื่องจากฉันได้ระบุชื่อไฟล์ต้นฉบับแทนชื่อคลาส

เราจำเป็นต้องระบุชื่อคลาสที่มีวิธีการหลักให้กับล่าม


ใช่. ดูตัวอย่าง # 2 ของฉันในวิธีที่ไม่ถูกต้องเพื่อระบุชื่อคลาส !!
สตีเฟ่นซี

7

สิ่งนี้อาจช่วยคุณได้หากกรณีของคุณเป็นของฉันโดยเฉพาะ: ในฐานะผู้เริ่มต้นฉันพบปัญหานี้เมื่อฉันพยายามเรียกใช้โปรแกรม Java

ฉันรวบรวมมันเช่นนี้:

javac HelloWorld.java

และฉันพยายามเรียกใช้ด้วยนามสกุลเดียวกัน:

java Helloworld.java

เมื่อฉันลบ.javaและเขียนคำสั่งเช่นjava HelloWorldนั้นโปรแกรมทำงานได้อย่างสมบูรณ์แบบ :)


2
นี่เป็นเพราะคุณกำลังดำเนินการรุ่นที่รวบรวมของ. java ของคุณ จริงๆแล้วมันกำลังดำเนินการไฟล์. class
Jason V

สำหรับบันทึกนี้เป็นเช่นเดียวกับเหตุผล # 1 ตัวอย่าง # 5 ในคำตอบของฉัน ...
Stephen C

6

คำตอบทั้งหมดที่นี่นำไปสู่ผู้ใช้ Windows ที่ดูเหมือน สำหรับ Mac คั่น classpath คือไม่: ;ในฐานะที่เป็นข้อผิดพลาดการตั้งค่า classpath ที่ใช้;ไม่ได้ถูกส่งออกไปแล้วนี่อาจเป็นเรื่องยากที่จะค้นพบว่ามาจาก Windows กับ Mac

นี่คือคำสั่ง Mac ที่สอดคล้องกัน:

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

ในตัวอย่างนี้แพคเกจคือcom.testและlibโฟลเดอร์จะรวมอยู่ใน classpath


2
บน Linux เช่นเดียวกับบน Mac
Alex78191

ทำไมถึง/*จำเป็น?
Alex78191

มันเป็นไวยากรณ์สัญลักษณ์ (ไม่บังคับคุณสามารถระบุรายชื่อ JAR ได้อย่างชัดเจน)
Stephen C

6

ป้อนคำอธิบายรูปภาพที่นี่

ตำแหน่งไฟล์คลาส: C: \ test \ com \ company

ชื่อไฟล์: Main.class

ชื่อคลาสที่ผ่านการรับรองโดยสมบูรณ์: com.company.Main

คำสั่งบรรทัดคำสั่ง:

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

โปรดทราบที่นี่ว่าคลาสพา ธ ไม่รวม \ com \ company


6

ฉันใช้เวลาพอสมควรในการพยายามแก้ไขปัญหานี้ ฉันคิดว่าฉันตั้ง classpath ไม่ถูกต้อง แต่ปัญหาคือฉันพิมพ์:

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

แทน:

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

ฉันคิดว่าความหมายของการรับรองแบบเต็มหมายถึงการรวมชื่อพา ธ เต็มแทนชื่อแพคเกจแบบเต็ม


ฉันได้อัปเดตคำตอบของฉันเพื่อพยายามแก้ไขความสับสนนั้น
สตีเฟ่นซี

2
สิ่งเหล่านี้ไม่ถูกต้อง ชั้นจะต้องได้รับเป็นutilities.myapp.Coolหรืออะไรก็ตามชื่อแพคเกจของมันคือถ้ามี
user207421

5

ก่อนอื่นกำหนดเส้นทางโดยใช้คำสั่งนี้;

set path="paste the set path address"

จากนั้นคุณต้องโหลดโปรแกรม พิมพ์ "cd (ชื่อโฟลเดอร์)" ในไดรฟ์ที่จัดเก็บและรวบรวม ตัวอย่างเช่นหากโปรแกรมของฉันเก็บไว้ในไดรฟ์ D ให้พิมพ์ "D:" กด Enter และพิมพ์ "cd (ชื่อโฟลเดอร์)"


4
สิ่งนี้ไม่ได้ช่วยอะไร คำถามนี้เกี่ยวกับโปรแกรม Java ไม่ใช่โปรแกรมทั่วไป Java ไม่ได้ใช้ PATH เพื่อค้นหาสิ่งใดและถ้า "cd" ช่วยคุณได้ด้วยโชคดีแทนที่จะใช้วิจารณญาณ
สตีเฟนซี

if "cd" helps then it by luck rather than by judgement. นี่เป็นสิ่งที่ผิด (ฉันเชื่อ) เนื่องจาก java ใช้ไดเรกทอรีปัจจุบัน.เป็นส่วนหนึ่งของ classpath โดยค่าเริ่มต้น
GKFX

2
@GKFX - นั่นคือสิ่งที่ฉันหมายถึง ถ้าคุณไม่ทราบว่าคุณกำลังใช้ classpath เริ่มต้น (หรือ classpath ที่มี "." อยู่) "cd" จะไม่มีผลใด ๆ วิธีแก้ปัญหานี้ทำงานได้โดยโชคดี (เช่นการคาดเดา / หวังว่า "." อยู่ใน classpath) มากกว่าโดยการตัดสิน (เช่นการตรวจสอบว่า "." อยู่บน classpath) นอกจากนี้คุณไม่ถูกต้องเกี่ยวกับค่าเริ่มต้น Java ใช้ "." เป็น classpath โดยค่าเริ่มต้นไม่ได้เป็นส่วนหนึ่งของ classpath โดยค่าเริ่มต้น
Stephen C

5

สิ่งที่แก้ไขปัญหาในกรณีของฉันคือ:

คลิกขวาที่โครงการ / ระดับคุณต้องการเรียกใช้แล้ว->Run As Run Configurationsจากนั้นคุณควรแก้ไขการกำหนดค่าที่มีอยู่หรือเพิ่มใหม่ด้วยวิธีต่อไปนี้:

เปิดClasspathแท็บคลิกที่Advanced...ปุ่มแล้วเพิ่มbinโฟลเดอร์ของโครงการของคุณ


5

หากคุณใช้Mavenเพื่อสร้างไฟล์ JAR โปรดตรวจสอบให้แน่ใจว่าระบุคลาสหลักในไฟล์ 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>

4

นี่เป็นกรณีเฉพาะ แต่เมื่อฉันมาที่หน้านี้เพื่อค้นหาวิธีแก้ปัญหาและไม่พบมันฉันจะเพิ่มที่นี่

Windows (ทดสอบกับ 7) ไม่ยอมรับอักขระพิเศษ (เช่นá) ในชื่อคลาสและแพ็คเกจ แม้ว่า Linux จะทำเช่นนั้น

ฉันพบสิ่งนี้เมื่อฉันสร้าง.jarใน NetBeans และพยายามเรียกใช้ในบรรทัดคำสั่ง มันทำงานใน NetBeans แต่ไม่ใช่ในบรรทัดคำสั่ง


4

บน Windows ให้ใส่.;ค่า CLASSPATH ในตอนต้น

ส่วน (จุด) หมายถึง "ดูในไดเรกทอรีปัจจุบัน" นี่คือทางออกที่ถาวร

นอกจากนี้คุณสามารถตั้งค่า "ครั้งเดียว" CLASSPATH=%CLASSPATH%;.กับชุด สิ่งนี้จะคงอยู่ตราบเท่าที่หน้าต่างคำสั่งของคุณเปิดอยู่


1
คำแนะนำนี้อาจช่วยได้หรือไม่ มันจะช่วยถ้าต้นเรียนที่มีชั้นเรียนในไดเรกทอรีปัจจุบัน มันจะไม่เกิดขึ้นถ้าพวกเขาไม่ใช่ ฉันจะไม่ทำสิ่งนี้ แต่ฉันจะสร้างสคริปต์ตัวห่อหนึ่งซับที่ทำงานหรือไม่ว่าผู้ใช้อยู่ในไดเรกทอรี "ขวา"
สตีเฟ่นซี

4

คุณต้องทำสิ่งนี้จากsrcโฟลเดอร์ ที่นั่นคุณพิมพ์บรรทัดคำสั่งต่อไปนี้:

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

สมมติว่าคลาสของคุณถูกเรียกใช้CommandLine.classและโค้ดมีลักษณะดังนี้:

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]);
            }
        }
    }

จากนั้นคุณควรcdไปที่โฟลเดอร์ src และคำสั่งที่คุณต้องการเรียกใช้จะมีลักษณะดังนี้:

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

และผลลัพธ์บนบรรทัดคำสั่งจะเป็น:

args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100

2
ไม่สามารถเรียกคลาสได้ "CommandLine.class" นั่นจะเป็นข้อผิดพลาดทางไวยากรณ์ของ Java (สิ่งที่คุณหมายถึงคือไฟล์ที่มีคลาสที่คอมไพล์เรียกว่า "CommandLine.class" ... ) ปัญหาอีกข้อคือคำสั่งของคุณที่จะ "cd to the source directory" ใช้งานได้เฉพาะเมื่อคุณคอมไพล์รหัส >> ลงใน << แผนผังไดเรกทอรีต้นทาง สุดท้ายหากคอมไพล์ของคุณใช้อาร์กิวเมนต์ "-cp" คุณต้องมีค่าเทียบเท่าเมื่อคุณรัน
สตีเฟ่นซี

ในโครงการของฉันฉันมีโฟลเดอร์ src และโฟลเดอร์ bin ที่รูท ฉันต้องcdเข้าไปsrcแล้วรันคำสั่งjava ../bin com.blah.blah.MyClassที่ใช้งานได้สำหรับฉัน ขอบคุณมากสำหรับเคล็ดลับ!
tamj0rd2

3

ใน Java บางครั้งเมื่อคุณเรียกใช้ JVM จากบรรทัดคำสั่งโดยใช้โปรแกรมจาวาและพยายามเริ่มโปรแกรมจากไฟล์คลาสที่มี public void main (PSVM) คุณอาจพบข้อผิดพลาดด้านล่างแม้ว่าพารามิเตอร์ classpath JVM นั้นถูกต้องและมีไฟล์คลาสอยู่บน classpath:

Error: main class not found or loaded

สิ่งนี้จะเกิดขึ้นหากไฟล์คลาสที่มี PSVM ไม่สามารถโหลดได้ เหตุผลหนึ่งที่เป็นไปได้คือคลาสอาจใช้อินเตอร์เฟสหรือขยายคลาสอื่นที่ไม่ได้อยู่ใน classpath โดยปกติถ้าคลาสไม่ได้อยู่ใน classpath ข้อผิดพลาดที่ส่งออกจะระบุว่าเป็นเช่นนั้น แต่ถ้าคลาสที่ใช้นั้นถูกขยายหรือนำไปใช้จาวาจะไม่สามารถโหลดคลาสเองได้

การอ้างอิง: https://www.computingnotes.net/java/error-main-class-not-found-or-loaded/


1
คุณอ่านคำตอบที่ยอมรับแล้วหรือยัง? คำตอบของคุณเพิ่มอะไรใหม่ ๆ ?
สตีเฟ่นซี

1
@StephenC ฉันพยายามค้นหาเหตุผลในรายการของคุณโดยดูที่หมวด "เหตุผล" และคะแนนของพวกเขา ฉันไม่พบจุดที่ตรงกันในชื่อ "เหตุผล # 1" และ "เหตุผล # 2" ไม่ได้มองใกล้กับกรณีของฉัน (เพราะฉันแน่ใจว่าไม่มีปัญหากับ classpath เอง) ฉันพบสาเหตุจากการทำการทดลองและฉันประหลาดใจที่ในกรณีของฉันเกิดข้อผิดพลาด "ไม่พบคลาสหลัก" ปรากฏขึ้นเนื่องจากการใช้ส่วนต่อประสานไม่ได้อยู่ในเส้นทางของชั้นเรียน แน่นอนคุณสามารถพูดว่า "คุณควรอ่านทุกอย่างที่อธิบายไว้ในโพสต์" แต่ดูเหมือนว่ารายการเหตุผลของคุณสามารถปรับปรุงได้
gumkins

3

เมื่อเรียกใช้javaกับ-cpตัวเลือกตามที่โฆษณาใน Windows PowerShell คุณอาจได้รับข้อผิดพลาดที่มีลักษณะบางอย่างเช่น:

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

เพื่อให้ PowerShell ยอมรับคำสั่งอาร์กิวเมนต์ของ-cpตัวเลือกจะต้องมีอยู่ในเครื่องหมายคำพูดเช่นเดียวกับใน:

java -cp 'someDependency.jar;.' ClassName

การขึ้นรูปคำสั่งด้วยวิธีนี้จะช่วยให้กระบวนการ Java อาร์กิวเมนต์ classpath ได้อย่างถูกต้อง


3

ฉันยังประสบข้อผิดพลาดที่คล้ายกันขณะทดสอบการเชื่อมต่อ Java MongoDB JDBC ฉันคิดว่ามันเป็นการดีที่จะสรุปวิธีแก้ปัญหาสุดท้ายของฉันในระยะสั้นเพื่อให้ในอนาคตใครก็ตามสามารถดูคำสั่งสองคำสั่งได้โดยตรงและเป็นการดีที่จะดำเนินการต่อไป

สมมติว่าคุณอยู่ในไดเรกทอรีที่มีไฟล์ Java และการอ้างอิงภายนอก (ไฟล์ JAR) ของคุณ

รวบรวม:

javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
  • -cp - อาร์กิวเมนต์ classpath; ส่งผ่านไฟล์ JAR ที่อ้างถึงทั้งหมดทีละไฟล์
  • * .java - นี่คือไฟล์คลาส Java ที่มีวิธีการหลัก sdsd

วิ่ง:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • โปรดสังเกตโคลอน (Unix) / เครื่องหมายจุลภาค (Windows) หลังจากไฟล์ JAR อ้างอิงทั้งหมดสิ้นสุด
  • ในตอนท้ายให้สังเกตชื่อคลาสหลักโดยไม่มีส่วนขยายใด ๆ (ไม่ใช่. class หรือ. java)

ทั้งหมดนี้ถือว่า 1) JavaMongoDBConnectionไม่มีแพ็คเกจและ 2) คุณไม่เปลี่ยนไดเรกทอรี มันคือการพูดน้อยเปราะบาง และโดยไม่ได้อธิบายปัญหาก็จะนำไปสู่มือใหม่ลองใช้วิธีนี้ในสถานการณ์ที่มันจะไม่ทำงาน ในระยะสั้นมันกระตุ้นให้ "เทคนิคการเขียนโปรแกรมวูดู": en.wikipedia.org/wiki/Voodoo_programming
สตีเฟนซี

3

เอาล่ะมีคำตอบมากมายอยู่แล้ว แต่ก็ไม่มีใครพูดถึงกรณีที่การอนุญาตของไฟล์เป็นตัวการ

เมื่อรันผู้ใช้อาจไม่สามารถเข้าถึงไฟล์ JAR หรือหนึ่งในไดเรกทอรีของพา ธ ตัวอย่างเช่นพิจารณา:

ไฟล์ Jar ใน /dir1/dir2/dir3/myjar.jar

ผู้ใช้ 1 ที่เป็นเจ้าของไฟล์ JAR สามารถทำได้:

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

แต่มันก็ยังไม่ทำงาน:

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

นี่เป็นเพราะผู้ใช้ที่กำลังทำงาน (User2) ไม่มีสิทธิ์เข้าถึง dir1, dir2 หรือ javalibs หรือ dir3 มันอาจทำให้บางคนถั่วเมื่อ User1 สามารถดูไฟล์และสามารถเข้าถึงพวกเขา แต่ข้อผิดพลาดยังคงเกิดขึ้นสำหรับ User2


2

ฉันได้รับข้อผิดพลาดนี้หลังจากทำmvn eclipse:eclipse สิ่งนี้ทำให้.classpathไฟล์ของฉันยุ่งเล็กน้อย

ต้องเปลี่ยนสาย.classpathจาก

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

ถึง

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

2

ฉันไม่สามารถแก้ไขปัญหานี้ได้ด้วยวิธีแก้ไขปัญหาที่ระบุไว้ที่นี่ (แม้ว่าคำตอบที่ระบุไว้มีไม่ต้องสงสัยเลย ฉันประสบปัญหานี้สองครั้งและทุกครั้งที่ฉันลองใช้วิธีแก้ไขปัญหาที่แตกต่างกัน (ใน Eclipse IDE)

  • ประการแรกฉันได้พบกับmainวิธีการหลายวิธีในชั้นเรียนที่แตกต่างกันของโครงการของฉัน ดังนั้นฉันจึงลบmainเมธอดออกจากคลาสที่ตามมา
  • ประการที่สองฉันลองทำตามวิธีแก้ปัญหา:
    1. คลิกขวาที่ไดเรกทอรีโครงการหลักของฉัน
    2. มุ่งหน้าไปยังแหล่งที่มาแล้วล้างข้อมูลและยึดกับการตั้งค่าเริ่มต้นและบนเสร็จสิ้น หลังจากงานพื้นหลังบางอย่างคุณจะถูกนำไปยังไดเรกทอรีโครงการหลักของคุณ
    3. หลังจากนั้นฉันปิดโปรเจ็กต์เปิดใหม่และบูมในที่สุดฉันก็แก้ปัญหาได้

1
mainวิธีการลบจะไม่สามารถแก้ไขปัญหาได้ ไม่มีอะไรผิดปกติทางเทคนิคกับแอปพลิเคชันที่มีจุดเข้าใช้หลายจุด
สตีเฟนซี
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.