大写和NoClassDefFoundError与ClassNotFoundException

时间:2011-11-12 14:32:36

标签: java classloader platform-independent

我看到跨平台的差异有关Class.forName()何时抛出ClassNotFoundException以及何时抛出NoClassDefFoundError。这个行为在某个地方定义得很好,还是我偶然发现了一个错误?

考虑以下代码(默认包中的独立java文件):

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
  }
}

代码在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

它在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)

Windows上的输出是有意义的:因为文件系统不区分大小写,所以JVM加载文件dLExceptionType.class,但该文件包含一个具有不同名称的类:DLExceptionType

然而,当我在Mac上运行代码时(具有区分大小写的文件系统和比Linux盒子更新的JVM),我获得与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)

2 个答案:

答案 0 :(得分:3)

HFS +(Mac Extended)通常不区分大小写。由于Mac OS 10.3 Apple推出了HFSX,它可以区分大小写(但不是默认设置)。如果您没有通过磁盘初始化指定该选项,那么您的卷很可能不区分大小写。

请参阅:http://en.wikipedia.org/wiki/HFS_Plus

答案 1 :(得分:0)

这里没有错误。您所看到的完全是由文件系统的区分大小写引起的。

在不区分大小写的文件系统上加载类dLExceptionType时,JVM可以找到文件dLException.class。但是,它包含的类没有名称dLException,这会导致NoClassDefFoundError。尝试在区分大小写的文件系统上加载此类时,JVM根本找不到该文件。

当JVM加载一个看似与其读取的文件名名称不同的类时,JVM会抛出消息中带有NoClassDefFoundError的{​​{1}}。您可以通过重命名类文件并尝试运行它来在任何文件系统上尝试此操作。