Чувствительность к регистру имен классов Java

Если кто-то записывает два общедоступных Java-класса с одним и тем же именем без учета регистра в разных каталогах, то оба класса не могут использоваться во время выполнения. (Я проверил это на Windows, Mac и Linux с несколькими версиями JVM HotSpot. Я не удивлюсь, если появятся другие JVM, где они могут использоваться одновременно.) Например, если я создаю класс с именемa и один по имениA вот так:

// 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";
    }
}

Три проекта Eclipse, содержащие приведенный выше код:доступно с моего сайта.

Если попробую я звонюmyCase на обоих классах вот так:

System.out.println(A.myCase());
System.out.println(a.myCase());

Проверка типов завершается успешно, но когда я запускаю файл класса, сгенерированный с помощью кода выше, я получаю:

Exception in thread "main" java.lang.NoClassDefFoundError: testcase/A (wrong name: testcase/a)

В Java имена, как правило, чувствительны к регистру. Некоторые файловые системы (например, Windows) нечувствительны к регистру, поэтому я не удивлен, что вышеупомянутое поведение происходит, но, похоже,wrong, К сожалению, спецификации Java странно не связаны с тем, какие классы видны.Спецификация языка Java (JLS), Java SE 7 Edition (Раздел 6.6.1, стр. 166) говорит:

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.

В Разделе 7.3 JLS определяет наблюдаемость модуля компиляции в очень расплывчатых терминах:

All the compilation units of the predefined package java and its subpackages lang and io are always observable. For all other packages, the host system determines which compilation units are observable.

Спецификация виртуальной машины Java так же расплывчато (раздел 5.3.1):

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.

Все это приводит к четырем вопросам в порядке убывания важности:

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? If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)? Is there any way to make HotSpot load a and A simultaneously? Would writing a custom class loader work?

Ответы на вопрос(3)

Ваш ответ на вопрос