Monday, July 5, 2010

ClassNotFoundException vs. NoClassDefFoundError

I have quite often seen people mistake a ClassNotFoundException for a NoClassDefFoundError and vice versa. So here is a break down on the differences.

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:

01public class App {
02 public static void main(String[] args) {
03 try {
04 App.class.getClassLoader().loadClass("NonExistent");
05 } catch (Throwable e) {
06 System.out.println(e.getClass().getName());
07 }
08
09 try {
10 new BadStatic();
11 } catch (Throwable e) {
12 System.out.println(e.getClass().getName());
13 System.out.println(e.getCause().getClass().getName());
14 }
15
16 try {
17 new BadStatic();
18 } catch (Throwable e) {
19 System.out.println(e.getClass().getName());
20 }
21
22 }
23
24}
25
26package za.co.classNotFoundBadness;
27
28public class BadStatic {
29
30 static {
31 if(true){
32 throw new IllegalArgumentException("I am a bad static initialiser.");
33 }
34 }
35
36 public BadStatic() {
37
38 }
39
40}

Output:
java.lang.ClassNotFoundException
First attempt:
java.lang.ExceptionInInitializerError
java.lang.IllegalArgumentException
Second attempt:
java.lang.NoClassDefFoundError

No comments:

Post a Comment