title: Case sensitivity of Java class names
body: <p>If one writes two public Java classes with the same case-insensitive name in different directories then both classes are not usable at runtime. (I tested this on Windows, Mac and Linux with several versions of the HotSpot JVM. I would not be surprised if there other JVMs where they are usable simultaneously.) For example, if I create a class named <code>a</code> and one named <code>A</code> like so:</p>
  
  <pre><code>// 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";
      }
  }
  </code></pre>
  
  <p>Three eclipse projects containing the code above are <a href="http://www.cs.cmu.edu/~jssunshi/stackoverflow/ClassNameCaseSensitivity.zip" rel="noreferrer">available from my website</a>.</p>
  
  <p>If try I calling <code>myCase</code> on both classes like so:</p>
  
  <pre><code>System.out.println(A.myCase());
  System.out.println(a.myCase());
  </code></pre>
  
  <p>The typechecker succeeds, but when I run the class file generate by the code directly above I get:</p>
  
  <blockquote>
    <p>Exception in thread "main" java.lang.NoClassDefFoundError: testcase/A (wrong name: testcase/a)</p>
  </blockquote>
  
  <p>In Java, names are in general case sensitive. Some file systems (e.g. Windows) are case insensitive, so I'm not surprised the above behavior happens, but it seems <em>wrong</em>. Unfortunately the Java specifications are oddly non-commital about which classes are visible. The <a href="http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf" rel="noreferrer">Java Language Specification (JLS), Java SE 7 Edition</a> (Section 6.6.1, page 166) says:</p>
  
  <blockquote>
    <p>If a class or interface type is declared  public, then it may be accessed by
    any code, provided that the compilation unit (§7.3) in which it is declared is
    observable.</p>
  </blockquote>
  
  <p>In Section 7.3, the JLS defines observability of a compilation unit in extremely vague terms:</p>
  
  <blockquote>
    <p>All the compilation units of the predefined package java and its subpackages lang 
    and io are always observable. For all other packages, <strong>the host system determines which compilation units are observable</strong>.</p>
  </blockquote>
  
  <p>The <a href="http://docs.oracle.com/javase/specs/jvms/se7/jvms7.pdf" rel="noreferrer">Java Virtual Machine Specification</a> is similarly vague (Section 5.3.1):</p>
  
  <blockquote>
    <p>The following steps are used to load and thereby create the nonarray class or 
    interface C denoted by [binary name] N using the bootstrap class loader [...]
    Otherwise, the Java virtual machine passes the argument N to an invocation of a
    method on the bootstrap class loader to search for a purported representation of C
    in a platform-dependent manner.</p>
  </blockquote>
  
  <p>All of this leads to four questions in descending order of importance:</p>
  
  <ol>
  <li>Are there any guarantees about which classes are loadable by the default class loader(s) in every JVM? In other words, can I implement a valid, but degenerate JVM, that won't load any classes except those in java.lang and java.io? </li>
  <li>If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)?</li>
  <li>Is there any way to make HotSpot load <code>a</code> and <code>A</code> simultaneously? Would writing a custom class loader work?</li>
  </ol>