java.lang.ClassNotFoundException: Class is not in the classpath, this could be due to there being 2 different active class loaders and each having different visibility, (this is often the case when working within application servers where you are not in control of the current class loaders), or just that the class is actually no there.
java.lang.NoClassDefFoundError: Is quite different, and generally means that the class is there but there was error reading the class definition. This quite often happens when an exception occurs in a static initializer block or static variable instantiation. The JVM throws a java.lang.ExceptionInInitializerError and the "unloads" the definition, any further attempts at accessing this class then result in a java.lang.NoClassDefFoundError.
While discussing it with a work colleague of mine he wrote the following code to illustrate the behaviour:
public class App { public static void main(String[] args) { try { App.class.getClassLoader().loadClass("NonExistent"); } catch (Throwable e) { System.out.println(e.getClass().getName()); } try { new BadStatic(); } catch (Throwable e) { System.out.println(e.getClass().getName()); System.out.println(e.getCause().getClass().getName()); } try { new BadStatic(); } catch (Throwable e) { System.out.println(e.getClass().getName()); } } } package za.co.classNotFoundBadness; public class BadStatic { static { if(true){ throw new IllegalArgumentException("I am a bad static initialiser."); } } public BadStatic() { } }
Output:
java.lang.ClassNotFoundException
First attempt:
java.lang.ExceptionInInitializerError
java.lang.IllegalArgumentException
Second attempt:
java.lang.NoClassDefFoundError
Wow, this is quite wrong. ClassNotFoundException and NoClassDefFoundError mean the same error at different stages. ClassNotFoundException is a checked exception, so it can only be thrown where one is expected. However in Java every reference to a class from code is a potential class lookup, so when that class is not found the NoClassDefFoundError is thrown. In fact AFAICT NoClassDefFoundError will always be caused by a ClassNotFoundException from the class loader doing the loading/linking.
ReplyDeleteNo that's not true. They both appear same but underlying cause is different. see this link which clearly differentiate between NoClassDefFoundError and ClassNotFoundException
DeleteCould you code / show me an example? This is based on what I have found in my experience, and I have supplied a little bit of code to show that the behavior I described does actually occur. I'll gladly amend the post if proven otherwise, and quite happy to learn something new...
ReplyDeleteFWIW, I also seem to remember differences across platforms. Can't remember the details but on Linux i got a ClassNotFoundException and on Windows (for the same operation) it gave a NoClassDefFoundError.
ReplyDeleteI avoid Linux like the plague actually... yeah I know, not a very "open source" thing to say... But anyone reading this with a linux setup care to run the code in the post and see if there are any differences... ?
ReplyDeleteI would think it very odd if there was... but stranger things have happened.
More likely that you classpath and /or resources were different between the 2... leading to different errors for completely different reasons.
If you run: java -verbose NonExistent
ReplyDeleteI think you can see an example of what Jevgeni described:
Exception in thread "main" java.lang.NoClassDefFoundError: NonExistent
Caused by: java.lang.ClassNotFoundException: NonExistent
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
Thanks for that... We may be onto something here,
ReplyDeletelets look at the whole stacktrace:
Exception in thread "main" java.lang.NoClassDefFoundError: NonExistent
Caused by: java.lang.ClassNotFoundException: NonExistent
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: NonExistent. Program will exit.
So the NoClassDefFoundError was caused by the ClassNotFoundException.
Now to try figure out the details...
There is "sun.misc.Launcher$AppClassLoader.loadClass" in the stacktrace,
I went searching for the code and it is defined as a static:
"static class AppClassLoader extends URLClassLoader "
So isn't what is happening exactly what my blog entry said,
the NoClassDefFoundError is caused by the JVM Unloading class because of an
Exception in a static (in this case it just happens to be a ClassNotFoundException) ?
Or am I missing something?
My test:
ReplyDeleteclass Test {
public static void main (String... a) {
try {
System.out.println(Foo.Z);
} catch (Throwable e) {
e.printStackTrace();
}
System.gc();
System.out.println("2nd");
try {
System.out.println(Foo.Z);
} catch (Throwable e) {
e.printStackTrace();
}
System.gc();
System.out.println("3nd");
System.out.println(new java.io.File("Foo.class").delete());
try {
System.out.println(Foo.Z);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
class Foo {
static {
if (1==1) {throw new IllegalArgumentException("oops");}
}
public static String Z = "1";
}
1st: java Test
java.lang.ExceptionInInitializerError
at Test.main(Test.java:4)
Caused by: java.lang.IllegalArgumentException: oops
at Foo.(Foo.java:5)
... 1 more
2nd
java.lang.NoClassDefFoundError: Could not initialize class Foo
at Test.main(Test.java:12)
3nd
true
java.lang.NoClassDefFoundError: Could not initialize class Foo
at Test.main(Test.java:21)
2nd java Test (there is no Foo class)
java.lang.NoClassDefFoundError: Foo
at Test.main(Test.java:4)
Caused by: java.lang.ClassNotFoundException: Foo
at java.net.URLClassLoader$1.run(Unknown Source)
2nd
java.lang.NoClassDefFoundError: Foo
at Test.main(Test.java:12)
3nd
false
java.lang.NoClassDefFoundError: Foo
at Test.main(Test.java:21)
So NoClassDefFoundError is more generic error.
Also ClassLoader caches classnames, so following calls will throw NoClassDefFoundError
CNFE is thrown when the requested class could not be found, while NCDE is thrown when a dependency of the requested class could not be found etc.
ReplyDeleteMua vé tại Aivivu, tham khảo
ReplyDeletevé máy bay đi Mỹ
vé máy bay quốc tế từ mỹ về việt nam
ve may bay tu canada ve viet nam
chuyến bay nhân đạo từ nhật về việt nam
bay từ hàn quốc về việt nam
Vé máy bay từ Đài Loan về VN
Chuyen bay cho chuyen gia nuoc ngoai