Search code examples
javaclassloaderplatform-independent

Capitalization and NoClassDefFoundError vs ClassNotFoundException


I'm seeing differences across platforms about when Class.forName() throws ClassNotFoundException and when it throws NoClassDefFoundError. Is this behavior well-defined somewhere, or have I stumbled across a bug?

Consider the following code (which is a standalone java file in the default package):

public class DLExceptionType {

  private static void printFindError(String name) {
    System.out.print(name + ": ");
    try {
      Class.forName(name);
      System.out.println("** no error **");
    } catch (Throwable e) {
      System.out.println(e);
    }
  }

  public static void main(String[] args) {
    printFindError("DLExceptionType");
    printFindError("dLExceptionType"); // note the mis-capitalization
  }
}

The code produces the expected output on Linux:

[eos18:~]$ java -version DLExceptionType
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)
[eos18:~]$ java DLExceptionType
DLExceptionType: ** no error **
dLExceptionType: java.lang.ClassNotFoundException: dLExceptionType

It produces a different, but understandable, output on Windows:

java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) Client VM (build 21.1-b02, mixed mode, sharing)

Y:\Temp>java DLExceptionType
DLExceptionType: ** no error **
dLExceptionType: java.lang.NoClassDefFoundError: dLExceptionType (wrong name:  DLExceptionType)

The output on Windows makes sense: Because the file system is not case sensitive, the JVM loads the file dLExceptionType.class, but that file contains a class with a different name: DLExceptionType

However, when I run the code on Mac (with has a case-sensitive file system and a newer JVM than the Linux box) I get the same output as Windows:

$ java -version
java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11-402-10M3527)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02-402, mixed mode)
$ java DLExceptionType
DLExceptionType: ** no error **
dLExceptionType: java.lang.NoClassDefFoundError: dLExceptionType (wrong name: DLExceptionType)

Solution

  • HFS+ (Mac Extended) is usually not case sensitive. Since Mac OS 10.3 Apple introduced HFSX which can be case sensitive (but is not the default). If you did not specify the option by the disk initialization then your volume is most likely case insensitive.

    See: http://en.wikipedia.org/wiki/HFS_Plus