NoClassDefFoundError (NCDFE) เกิดขึ้นเมื่อรหัสของคุณรัน "new Y ()" และไม่พบคลาส Y
อาจเป็นเพราะ Y หายไปจากตัวโหลดคลาสของคุณเช่นเดียวกับข้อคิดเห็นอื่น ๆ ที่แนะนำ แต่อาจเป็นได้ว่าคลาส Y ไม่ได้ลงชื่อหรือมีลายเซ็นไม่ถูกต้องหรือ Y ถูกโหลดโดย classloader อื่นที่ไม่สามารถมองเห็นได้ในรหัสของคุณ หรือแม้กระทั่งว่า Y ขึ้นอยู่กับ Z ซึ่งไม่สามารถโหลดได้ด้วยเหตุผลใด ๆ ข้างต้น
หากสิ่งนี้เกิดขึ้น JVM จะจดจำผลลัพธ์ของการโหลด X (NCDFE) และมันจะโยน NCDFE ใหม่ทุกครั้งที่คุณถามหา Y โดยไม่บอกสาเหตุ:
ชั้นเรียน {
คลาส b แบบคงที่ {}
โมฆะคงที่สาธารณะหลัก (String args []) {
System.out.println ("ความพยายามครั้งแรกใหม่ b ():");
ลอง {new b (); } catch (Throwable t) {t.printStackTrace ();}
System.out.println ("\ n วินาทีลองใหม่ b ():");
ลอง {new b (); } catch (Throwable t) {t.printStackTrace ();}
}
}
บันทึกสิ่งนี้เป็น a.java ที่ไหนสักแห่ง
รหัสนั้นพยายามที่จะยกตัวอย่างคลาส "b" ใหม่สองครั้งนอกเหนือจากนั้นไม่มีข้อบกพร่องใด ๆ และจะไม่ทำอะไรเลย
คอมไพล์โค้ดด้วยjavac a.java
, จากนั้นรัน a โดยการเรียกใช้java -cp . a
- มันควรพิมพ์ข้อความสองบรรทัดและมันก็จะทำงานได้ดีโดยไม่มีข้อผิดพลาด
จากนั้นลบไฟล์ "a $ b.class" (หรือเติมด้วยขยะหรือคัดลอก a.class ไป) เพื่อจำลองชั้นที่ขาดหายไปหรือเสียหาย นี่คือสิ่งที่เกิดขึ้น:
ความพยายามครั้งแรกใหม่ b ():
java.lang.NoClassDefFoundError: a $ b
ที่ a.main (a.java/5)
เกิดจาก: java.lang.ClassNotFoundException: a $ b
ที่ java.net.URLClassLoader $ 1.run (URLClassLoader.java:200)
ที่ java.security.AccessController.doPrivileged (วิธีดั้งเดิม)
ที่ java.net.URLClassLoader.findClass (URLClassLoader.java:188)
ที่ java.lang.ClassLoader.loadClass (ClassLoader.java:307)
ที่ sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:301)
ที่ java.lang.ClassLoader.loadClass (ClassLoader.java:252)
ที่ java.lang.ClassLoader.loadClassInternal (ClassLoader.java:320)
... อีก 1
ความพยายามครั้งที่สองใหม่ b ():
java.lang.NoClassDefFoundError: a $ b
ที่ a.main (a.java:7)
การเรียกใช้ครั้งแรกส่งผลให้ ClassNotFoundException (ส่งโดยตัวโหลดคลาสเมื่อไม่สามารถหาคลาสได้) ซึ่งต้องถูกล้อมรอบใน NoClassDefFoundError ที่ไม่ถูกตรวจสอบเนื่องจากโค้ดที่เป็นปัญหา ( new b()
) ควรใช้งานได้
แน่นอนว่าความพยายามครั้งที่สองจะล้มเหลวเช่นกัน แต่อย่างที่คุณเห็นว่าข้อยกเว้นที่ห่อไว้นั้นไม่มีอีกต่อไปเพราะ ClassLoader ดูเหมือนจะจำคลาสตัวโหลดที่ล้มเหลวได้ คุณเห็นเฉพาะ NCDFE ที่ไม่มีเงื่อนงำอย่างแน่นอนว่าเกิดอะไรขึ้น
ดังนั้นหากคุณเคยเห็น NCDFE โดยไม่มีสาเหตุคุณจำเป็นต้องดูว่าคุณสามารถติดตามย้อนกลับไปในครั้งแรกที่มีการโหลดคลาสเพื่อค้นหาสาเหตุของข้อผิดพลาด
-verbose
(เช่น-verbose:class -verbose:jni
) - แต่รายงาน mogsie ด้านล่างคำตอบของพวกเขาว่านี่ไม่ได้ให้ข้อมูลที่เป็นประโยชน์เพิ่มเติม :(