Celem jest napisanie kodu Java, który wykrywa wersję JVM polegającą na zmianach kompatybilności, skutkach ubocznych, błędach i / lub niezdefiniowanym zachowaniu, które działa w pewien sposób w jednej wersji i w inny sposób w innej wersji. Ponadto kod powinien być co najmniej nieco czytelny, bez poświęcania białych znaków i czytelnych nazw zmiennych.
Aby zapewnić ten cel, dokładne zasady formalne są następujące:
Kod musi być napisany w Javie i powinien wypisywać wersję JRE, w której jest uruchomiony.
Kod nie może używać żadnego interfejsu JDK lub JRE API specjalnie do wykrywania wersji Java lub który udostępnia wersję JDK lub JRE za darmo.
Kod nie może używać refleksji.
Kod jest wymagany tylko do pracy w Hotspot Java SE 5, 6 i 7, ale może działać w innych maszynach JVM.
Kod nie może używać bibliotek stron trzecich w ścieżce klasy.
Kod nie może uruchamiać żadnego innego procesu, Java lub nie.
Kod nie może używać zmiennych środowiskowych.
Kod nie może przeszukiwać systemu plików w poszukiwaniu wcześniej istniejących plików lub folderów.
Kod musi być zawarty w jednym pliku i wywoływany przez
public static void main(String[] args)
lubpublic static void main(String... args)
.Kod nie może wykorzystywać żadnych niepublicznych interfejsów API obecnych w środowisku JRE.
Kod nie może generować żadnego NoClassDefFoundError, NoSuchMethodError, ClassNotFoundException lub NoSuchMethodException podczas jego wykonywania.
Kod powinien działać w systemie odłączonym od Internetu lub od dowolnej sieci lokalnej.
Powinieneś wyjaśnić, dlaczego zachowuje się w jeden sposób w jednej wersji, a inny w innej wersji.
Punktacja
Metodą stosowaną do pomiaru najlepszego rozwiązania jest max (n / s), gdzie n oznacza liczbę wykrytych różnych wersji Java bez naruszenia którejkolwiek z tych zasad (co najmniej wersje 5, 6 i 7), a s jest liczbą tokenów leksykalnych w roztworze.
źródło
Odpowiedzi:
6/102 = 0,0588
Wykrywa 6 wersji. Posiada 102 tokeny leksykalne (spadek z 103, po Usunąłem
public
wpublic class
).Java 1.1 wprowadziła kodowanie znaków i algorytmy kryptograficzne w Javie. Późniejsze wersje dodały więcej kodowań i algorytmów. Ten program próbuje używać kodowań i algorytmów, dopóki nie wyłapie wyjątku. Oczekuję, że zostanie wygenerowane brakujące kodowanie
java.io.UnsupportedEncodingException
i brakujący algorytmjava.security.NoSuchAlgorithmException
.Miałem stary Macintosh PowerPC z czterema starymi wersjami Javy. Moja maszyna OpenBSD ma jeszcze dwie wersje, więc przetestowałem te sześć wersji:
Ten program może również działać w JamVM 1.5.4 i gcj 4.8.2 dla OpenBSD, ale nie identyfikuje ich jako różnych implementacji. Drukuje tylko „Java 5”.
Środowisko wykonawcze Mac OS dla Java
Dzięki „Napisz raz, uruchom wszędzie!”, Mogę napisać ten program raz, skompilować go raz i uruchomić jedną GuessVersion.class na wszystkich ośmiu maszynach wirtualnych. Potrzebuję kompilatora dla Java 1.1, najstarszej wersji w mojej kolekcji.
Mój kompilator jest
javac
narzędziem z MRJ SDK 2.2. Ponieważ Classic Mac OS nie miał wiersza poleceń,javac
jest dość graficznym narzędziem, w którym wybieram pliki i opcje i klikam „Do Javac”. Po edycji kodu po prostu ponownie klikam „Do Javac”.Najprostszym sposobem na uruchomienie GuessVersion.class jest otwarcie go w JBindery, innym narzędziu z MRJ SDK 2.2. Środowisko wykonawcze to MRJ 2.2.6, implementacja Java 1.1.8.
źródło
Nie jestem pewien, jaki jest mój wynik, ponieważ zależy to od tego, co dokładnie uważasz za leksykalny, ale staram się nadużywać tego systemu liczenia tak długo, jak to możliwe, długim ciągiem ...
Zależy to również od tego, czy liczysz to jako identyfikację 7 różnych wersji, czy 16 ... (Można to trywialnie rozszerzyć do 190).
Działa, próbując zdefiniować interfejs w niestandardowym module ładującym klasy z malejącymi głównymi numerami wersji formatu klasy. Pierwszy, który nie rzuca,
java.lang.UnsupportedClassVersionError
odpowiada wersji maszyny wirtualnej.źródło
String... args
.protected Class loadClass(String name, boolean resolve) { return Object.class; }
. Obecne dokumenty API nie wspominają o tym, jak była to abstrakcyjna metoda przed Javą 1.2. Zwracam Object.class, ponieważ metoda otrzymuje jedno wywołanie „java.lang.Object”.Algorytm internowania zmienił się między Java 6 a 7. Zobacz /programming//a/7224864/540552
XMLGregorianCalendar.equals (null) używany do zgłaszania wyjątku NullPointerException w java 5, ale zostało to naprawione w java 6. Zobacz http://bugs.sun.com/view_bug.do?bug_id=6285370
10096928785 żetonów tutaj. Podziękowania dla Petera Taylora za zmniejszenie 7 tokenów.źródło
DatatypeConfigurationException
nie zostanie rzucony.int a
ale zainicjuj go natychmiast, abyif
blok stał się pusty. Neguj warunek, usuń pozostałe i użyj--
zamiast bezpośredniego przypisania doa
.