Sensibilidade ao caso de nomes de classes Java

Se alguém escrever duas classes Java públicas com o mesmo nome que não diferencia maiúsculas de minúsculas em diretórios diferentes, as duas classes não serão utilizáveis ​​no tempo de execução. (Eu testei isso no Windows, Mac e Linux com várias versões do HotSpot JVM. Eu não ficaria surpreso se houver outras JVMs onde elas possam ser usadas simultaneamente.) Por exemplo, se eu criar uma classe chamadaa e um chamadoA igual 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";
    }
}

Três projetos de eclipse contendo o código acima sãodisponível no meu site.

Se eu tentar ligarmyCase em ambas as classes assim:

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

O typechecker é bem-sucedido, mas quando executo o arquivo de classe gerado pelo código diretamente acima eu recebo:

Exceção no thread "main" java.lang.NoClassDefFoundError: testcase / A (nome errado: testcase / a)

Em Java, os nomes geralmente são sensíveis a maiúsculas e minúsculas. Alguns sistemas de arquivos (por exemplo, o Windows) são insensíveis a maiúsculas e minúsculas, por isso não me surpreende que o comportamento acima aconteça, mas pareceerrado. Infelizmente, as especificações do Java são estranhamente não-commital sobre quais classes são visíveis. oJava Language Specification (JLS), Java SE 7 Edition (Seção 6.6.1, página 166) diz:

Se uma classe ou tipo de interface é declarado público, então ele pode ser acessado por qualquer código, desde que a unidade de compilação (§7.3) na qual ele é declarado seja observável.

Na Seção 7.3, o JLS define a observabilidade de uma unidade de compilação em termos extremamente vagos:

Todas as unidades de compilação do pacote predefinido java e seus subpacotes lang e io são sempre observáveis. Para todos os outros pacotes,o sistema host determina quais unidades de compilação são observáveis.

oEspecificação de Java Virtual Machine é igualmente vago (Seção 5.3.1):

As etapas a seguir são usadas para carregar e, assim, criar a classe nonarray ou interface C denotada por [nome binário] N usando o carregador de classes de bootstrap. Caso contrário, a máquina virtual Java passa o argumento N para uma invocação de um método em o carregador de classes de bootstrap para procurar uma representação suposta de C de uma maneira dependente da plataforma.

Tudo isso leva a quatro perguntas em ordem decrescente de importância:

Há alguma garantia sobre quais classes podem ser carregadas pelo (s) carregador (es) de classes padrão em cada JVM? Em outras palavras, posso implementar uma JVM válida, mas degenerada, que não carregará nenhuma classe, exceto aquelas em java.lang e java.io?Se houver alguma garantia, o comportamento no exemplo acima viola a garantia (ou seja, o comportamento é um bug)?Existe alguma maneira de fazer o carregamento HotSpota eA simultaneamente? Será que escrever um carregador de classes personalizado funcionaria?

questionAnswers(3)

yourAnswerToTheQuestion