If you write two open Java classes with the same name case insensitive in different directories, then both classes cannot be used at run time. (I tested this on Windows, Mac, and Linux with several versions of JSM HotSpot. I wonβt be surprised if there are other JVMs where they can be used at the same time.) For example, if I create a class named a and one named a like this:
// lowercase/src/testcase/a.java package testcase; public class a { public static String myCase() { return "lower"; } } // uppercase/src/testcase/A.java package testcase; public class A { public static String myCase() { return "upper"; } }
Three eclipse projects containing the code above are available from my site .
If I try to call myCase in both classes, for example:
System.out.println(A.myCase()); System.out.println(a.myCase());
Typechecker error, but when I run the class file, generating the code directly above, I get:
Exception in thread "main" java.lang.NoClassDefFoundError: testcase / A (invalid name: testcase / a)
In Java, names are generally case sensitive. Some file systems (like Windows) are case insensitive, so I'm not surprised how this happens, but it seems wrong. Unfortunately, the Java specifications are strangely unspecific which classes are visible. The Java Language Specification (JLS), Java SE 7 Edition (section 6.6.1, p. 166) states:
If a class or interface type is declared publicly available, any code can be assigned to it, provided that the compilation unit (Β§7.3) in which it is declared is observable.
In Section 7.3, JLS defines the observability of a compilation unit in extremely vague terms:
All compilation units of the predefined java package and its subpackages lang and io are always observable. For all other packages, the host system determines which compilation units are observable .
The Java virtual machine specification is also vague (section 5.3.1):
The following steps are used to load and thereby create a nonarray class or C interface, denoted by [binary name] N, using the bootstrap class loader [...] Otherwise, the Java virtual machine passes argument N to the bootstrap class loader method to find the intended representation C depending on the platform.
All this leads to four questions in decreasing order of importance:
- Are there any guarantees as to which classes are loaded by the default class loader in each JVM? In other words, can I implement a valid but degenerate JVM that will not load any classes other than those specified in java.lang and java.io?
- If there are any guarantees, the behavior in the above example violates the guarantee (i.e. is the behavior an error)?
- Is there a way to make HotSpot
a and a boot at the same time? Will a custom classloader write?