Ziel ist es, Java-Code zu schreiben, der die JVM-Version anhand von Kompatibilitätsänderungen, Nebenwirkungen, Fehlern und / oder undefiniertem Verhalten erkennt, die in einer Version auf eine andere Art und Weise funktionieren. Außerdem sollte der Code mindestens ein bisschen lesbar sein, ohne auf Leerzeichen und lesbare Variablennamen zu verzichten.
Um dieses Ziel zu erreichen, lauten die genauen formalen Regeln:
Der Code muss in Java geschrieben sein und die JRE-Version ausgeben, in der er ausgeführt wird.
Der Code darf keine JDK- oder JRE-API verwenden, die speziell für die Erkennung der Java-Version bereitgestellt wurde oder die JDK- oder JRE-Version kostenlos zur Verfügung stellt.
Der Code darf keine Reflektion verwenden.
Der Code ist nur für die Verwendung in Hotspot Java SE 5, 6 und 7 erforderlich, kann jedoch auch in anderen JVMs verwendet werden.
Der Code darf keine Bibliotheken von Drittanbietern im Klassenpfad verwenden.
Der Code darf keinen anderen Prozess starten, weder Java noch.
Der Code darf keine Umgebungsvariablen verwenden.
Der Code darf das Dateisystem nicht nach bereits vorhandenen Dateien oder Ordnern durchsuchen.
Der Code muss in einer einzigen Datei enthalten sein und über
public static void main(String[] args)
oder aufgerufen werdenpublic static void main(String... args)
.Der Code darf keine nicht öffentliche API verwenden, die in der JRE vorhanden ist.
Der Code darf während seiner Ausführung keine NoClassDefFoundError, NoSuchMethodError, ClassNotFoundException oder NoSuchMethodException generieren.
Der Code sollte auf einem System ausgeführt werden, das nicht mit dem Internet oder einem lokalen Netzwerk verbunden ist.
Sie sollten erklären, warum es sich in einer Version auf die eine und in einer anderen Version auf die andere Weise verhält.
Wertung
Die Methode zur Messung der besten Lösung ist max (n / s), wobei n die Anzahl der verschiedenen Java-Versionen ist, die erkannt wurden, ohne dass eine dieser Regeln verletzt wurde (mindestens Version 5, 6 und 7), und s die Anzahl der lexikalischen Token in der Lösung.
quelle
Antworten:
6/102 = 0,0588
Erkennt 6 Versionen. Hat 102 lexikalische Token (von 103 nach dem Löschen
public
inpublic class
).Java 1.1 führte Zeichenkodierungen und kryptografische Algorithmen in Java ein. In späteren Versionen wurden weitere Codierungen und Algorithmen hinzugefügt. Dieses Programm versucht, Kodierungen und Algorithmen zu verwenden, bis eine Ausnahme auftritt. Ich erwarte, dass eine fehlende Kodierung
java.io.UnsupportedEncodingException
und ein fehlender Algorithmus ausgelöst werdenjava.security.NoSuchAlgorithmException
.Ich hatte einen alten PowerPC Macintosh mit vier alten Java-Versionen. Meine OpenBSD-Maschine hat zwei weitere Versionen, deshalb habe ich diese sechs Versionen getestet:
Dieses Programm kann auch in JamVM 1.5.4 und gcj 4.8.2 für OpenBSD ausgeführt werden, identifiziert sie jedoch nicht als unterschiedliche Implementierungen. Es wird nur "Java 5" gedruckt.
Mac OS Runtime für Java
Dank "Einmal schreiben, überall ausführen!" Kann ich dieses Programm einmal schreiben, einmal kompilieren und in allen acht virtuellen Maschinen eine GuessVersion.class ausführen. Ich benötige einen Compiler für Java 1.1, die älteste Version meiner Sammlung.
Mein Compiler ist das
javac
Tool aus MRJ SDK 2.2. Da das klassische Mac OS keine Befehlszeile hatte,javac
ist es ein hübsches grafisches Tool, in dem ich Dateien und Optionen auswähle und auf "Do Javac" klicke. Nachdem ich meinen Code bearbeitet habe, klicke ich erneut auf "Do Javac".Der einfachste Weg, GuessVersion.class auszuführen, besteht darin, es in JBindery, einem anderen Tool aus MRJ SDK 2.2, zu öffnen. Die Laufzeit ist MRJ 2.2.6, eine Implementierung von Java 1.1.8.
quelle
Ich bin mir nicht sicher, wie hoch meine Punktzahl ist, da dies davon abhängt, was genau Sie als lexikalisches Token betrachten, aber ich versuche, dieses Zählsystem mit einer langen Zeichenfolge so weit wie möglich zu missbrauchen ...
Es hängt auch davon ab, ob Sie dies als Identifizierung von 7 verschiedenen Versionen oder 16 ... (Es könnte trivial auf 190 erweitert werden).
Es funktioniert, indem versucht wird, eine Schnittstelle in einem benutzerdefinierten Klassenladeprogramm mit absteigenden Hauptversionsnummern des Klassenformats zu definieren. Der erste, der kein wirft,
java.lang.UnsupportedClassVersionError
entspricht der VM-Version.quelle
String... args
.protected Class loadClass(String name, boolean resolve) { return Object.class; }
. In den aktuellen API-Dokumenten wird nicht erwähnt, dass dies vor Java 1.2 eine abstrakte Methode war. Ich gebe Object.class zurück, weil die Methode einen Aufruf für "java.lang.Object" erhält.Der interne Algorithmus wurde zwischen Java 6 und 7 geändert. Siehe /programming//a/7224864/540552
XMLGregorianCalendar.equals (null) wurde verwendet, um NullPointerException in Java 5 auszulösen, dies wurde jedoch in Java 6 behoben. Siehe http://bugs.sun.com/view_bug.do?bug_id=6285370
10096928785 Token hier. Vielen Dank an Peter Taylor für die Reduzierung von 7 Token.quelle
DatatypeConfigurationException
es nicht geworfen wird.int a
aber initialisieren Sie es sofort, damit derif
Block leer wird. Annullieren Sie die Bedingung, entfernen Sie das else und verwenden Sie--
anstelle der direkten Zuordnung zua
.