7

我看到跨平台的差异在于 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)
4

2 回答 2

3

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

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

于 2011-11-12T14:47:58.440 回答
0

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

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

每当 JVM 加载一个似乎与读取它的文件名具有不同名称的类时,消息中的 with 就会被抛出NoClassDefFoundError(wrong name: ...)您可以通过重命名类文件并尝试运行它来在任何文件系统上尝试此操作。

于 2011-11-12T16:39:12.667 回答