O objetivo é escrever código java que detecta a versão da JVM confiando em alterações de compatibilidade, efeitos colaterais, bugs e / ou comportamento indefinido que funcionam de uma maneira em uma versão e outra em outra versão. Além disso, o código deve ser pelo menos um pouco legível, sem sacrificar espaços em branco e nomes de variáveis legíveis.
Para garantir esse objetivo, as regras formais exatas são:
O código deve ser escrito em java e deve gerar a versão do JRE na qual está sendo executado.
O código não deve usar nenhuma API JDK ou JRE fornecida especificamente para detectar a versão java ou que fornece a versão JDK ou JRE gratuitamente.
O código não deve usar reflexão.
O código é necessário apenas para funcionar no Hotspot Java SE 5, 6 e 7, mas pode funcionar em outras JVMs.
O código não deve usar nenhuma biblioteca de terceiros no caminho de classe.
O código não deve iniciar nenhum outro processo, java ou não.
O código não deve usar variáveis de ambiente.
O código não deve procurar no sistema de arquivos procurando arquivos ou pastas preexistentes.
O código deve estar contido em um único arquivo e ser chamado via
public static void main(String[] args)
oupublic static void main(String... args)
.O código não deve usar nenhuma API não pública presente no JRE.
O código não deve gerar nenhum NoClassDefFoundError, NoSuchMethodError, ClassNotFoundException ou NoSuchMethodException durante sua execução.
O código deve ser executado em um sistema desconectado da Internet ou de qualquer rede local.
Você deve fornecer uma explicação de por que ele se comporta de uma maneira em uma versão e de outra maneira em outra versão.
Pontuação
O método usado para medir a melhor solução é max (n / s), em que n é o número de versões java diferentes detectadas sem violar nenhuma dessas regras (pelo menos as versões 5, 6 e 7) e s é o número de tokens lexicais na solução.
fonte
Respostas:
6/102 = 0,0588
Detecta 6 versões. Tem 102 símbolos lexicais (para baixo de 103, depois de ter suprimido
public
empublic class
).O Java 1.1 introduziu codificações de caracteres e algoritmos criptográficos no Java. Versões posteriores adicionaram mais codificações e algoritmos. Este programa tenta usar codificações e algoritmos até capturar uma exceção. Espero que uma codificação ausente seja lançada
java.io.UnsupportedEncodingException
e um algoritmo ausente seja lançadojava.security.NoSuchAlgorithmException
.Eu tinha um Macintosh PowerPC antigo com quatro versões antigas de Java. Minha máquina OpenBSD tem mais duas versões, então testei estas seis versões:
Este programa também pode ser executado no JamVM 1.5.4 e gcj 4.8.2 para OpenBSD, mas não os identifica como implementações diferentes. Ele imprime apenas "Java 5".
Tempo de execução do Mac OS para Java
Graças a "Escreva uma vez, execute em qualquer lugar!", Posso escrever este programa uma vez, compilá-lo uma vez e executar uma GuessVersion.class nas oito máquinas virtuais. Eu preciso de um compilador para Java 1.1, a versão mais antiga da minha coleção.
Meu compilador é a
javac
ferramenta do MRJ SDK 2.2. Como o Mac OS clássico não tinha linha de comando,javac
é uma ferramenta gráfica bastante bonita, onde seleciono arquivos e opções e clico em "Do Javac". Depois de editar meu código, basta clicar em "Do Javac" novamente.A maneira mais fácil de executar o GuessVersion.class é abri-lo no JBindery, outra ferramenta do MRJ SDK 2.2. O tempo de execução é MRJ 2.2.6, uma implementação do Java 1.1.8.
fonte
Não tenho certeza de qual é minha pontuação, porque depende do que você considera um símbolo lexical, mas estou tentando abusar do sistema de contagem o máximo possível com uma longa sequência ...
Também depende se você conta isso como identificando 7 versões diferentes ou 16 ... (Poderia ser estendido trivialmente até 190).
Ele funciona ao tentar definir uma interface em um carregador de classe personalizado com números de versão principais decrescentes do formato de classe. O primeiro que não lança um
java.lang.UnsupportedClassVersionError
corresponde à versão da VM.fonte
String... args
.protected Class loadClass(String name, boolean resolve) { return Object.class; }
. Os documentos atuais da API não mencionam como esse foi um método abstrato antes do Java 1.2. Retorno Object.class porque o método recebe uma chamada para "java.lang.Object".O algoritmo de internação mudou entre Java 6 e 7. Consulte /programming//a/7224864/540552
XMLGregorianCalendar.equals (null) usado para lançar NullPointerException no java 5, mas isso foi corrigido no java 6. Consulte http://bugs.sun.com/view_bug.do?bug_id=6285370
10096928785 tokens aqui. Agradecemos a Peter Taylor por reduzir 7 tokens.fonte
DatatypeConfigurationException
não será lançado.int a
mas inicialize imediatamente, para que oif
bloco fique vazio. Negue a condição, remova o else e use em--
vez da atribuição direta paraa
.