大写和NoClassDefFoundError与ClassNotFoundException

我看到跨平台的差异有关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) 

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

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

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

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

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

Interesting Posts