NoClassDefFoundError (NCDFE) трапляється, коли ваш код запускає "новий Y ()" і він не може знайти клас Y.
Це може бути просто те, що Y відсутній у вашому завантажувачі класів, як це пропонують інші коментарі, але може бути, що клас Y не підписаний або має недійсну підпис, або що Y завантажений іншим завантажувачем класів, який не видно для вашого коду , або навіть те, що Y залежить від Z, який не вдалося завантажити з жодної з перерахованих вище причин.
Якщо це станеться, то JVM запам’ятає результат завантаження X (NCDFE), і він буде просто кидати новий NCDFE кожен раз, коли ви попросите Y, не повідомляючи, чому:
клас {
статичний клас b {}
public static void main (String args []) {
System.out.println ("Перша спроба нового b ():");
спробуйте {new b (); } улов (Throwable t) {t.printStackTrace ();}
System.out.println ("\ nДруга спроба нового b ():");
спробуйте {new b (); } улов (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.javajanju)
Викликано: java.lang.ClassNotFoundException: a $ b
на java.net.URLClassLoader $ 1.run (URLClassLoader.java:200)
at java.security.AccessController.doPrivileged (Рідний метод)
на java.net.URLClassLoader.findClass (URLClassLoader.java:188)
на java.lang.ClassLoader.loadClass (ClassLoader.java:307)
at sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:301)
at java.lang.ClassLoader.loadClass (ClassLoader.java:252)
at 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 повідомляє нижче своєї відповіді, що це не дає додаткової корисної інформації :(