L'objectif est d'écrire du code java qui détecte la version JVM en s'appuyant sur les changements de compatibilité, les effets secondaires, les bugs et / ou les comportements indéfinis qui fonctionnent d'une manière dans une version et d'une autre manière dans une autre version. En outre, le code doit être au moins un peu lisible, sans sacrifier les espaces blancs et les noms de variables lisibles.
Pour garantir cet objectif, les règles formelles exactes sont les suivantes:
Le code doit être écrit en java et doit afficher la version JRE dans laquelle il s'exécute.
Le code ne doit utiliser aucune API JDK ou JRE fournie spécifiquement pour détecter la version java ou qui donne la version JDK ou JRE gratuitement.
Le code ne doit pas utiliser de réflexion.
Le code est uniquement requis pour fonctionner dans Hotspot Java SE 5, 6 et 7, mais peut fonctionner dans d'autres JVM.
Le code ne doit utiliser aucune bibliothèque tierce dans le chemin de classe.
Le code ne doit démarrer aucun autre processus, Java ou non.
Le code ne doit pas utiliser de variables d'environnement.
Le code ne doit pas rechercher dans le système de fichiers à la recherche de fichiers ou de dossiers préexistants.
Le code doit être contenu dans un seul fichier et être appelé via
public static void main(String[] args)
oupublic static void main(String... args)
.Le code ne doit utiliser aucune API non publique présente dans le JRE.
Le code ne doit générer aucune NoClassDefFoundError, NoSuchMethodError, ClassNotFoundException ou NoSuchMethodException pendant son exécution.
Le code doit s'exécuter dans un système déconnecté d'Internet ou de tout réseau local.
Vous devez expliquer pourquoi il se comporte d'une manière dans une version et d'une autre manière dans une autre version.
Notation
La méthode utilisée pour mesurer la meilleure solution est max (n / s), où n est le nombre de versions java différentes détectées sans violer aucune de ces règles (au moins les versions 5, 6 et 7) et s est le nombre de jetons lexicaux. dans la solution.
la source
Réponses:
6/102 = 0,0588
Détecte 6 versions. A 102 jetons lexicaux (au lieu de 103, après avoir supprimé
public
danspublic class
).Java 1.1 a introduit des encodages de caractères et des algorithmes cryptographiques à Java. Les versions ultérieures ont ajouté plus d'encodages et d'algorithmes. Ce programme essaie d'utiliser des encodages et des algorithmes jusqu'à ce qu'il intercepte une exception. J'attends un encodage manquant à lancer
java.io.UnsupportedEncodingException
et un algorithme manquant à lancerjava.security.NoSuchAlgorithmException
.J'avais un vieux PowerPC Macintosh avec quatre anciennes versions de Java. Ma machine OpenBSD a deux autres versions, j'ai donc testé ces six versions:
Ce programme peut également s'exécuter dans JamVM 1.5.4 et gcj 4.8.2 pour OpenBSD, mais ne les identifie pas comme des implémentations différentes. Il imprime uniquement "Java 5".
Mac OS Runtime pour Java
Grâce à "Écrire une fois, exécuter partout!", Je peux écrire ce programme une fois, le compiler une fois et exécuter une GuessVersion.class sur les huit machines virtuelles. J'ai besoin d'un compilateur pour Java 1.1, la plus ancienne version de ma collection.
Mon compilateur est l'
javac
outil de MRJ SDK 2.2. Parce que le Mac OS classique n'avait pas de ligne de commande,javac
est un joli outil graphique où je sélectionne les fichiers et les options et cliquez sur "Do Javac". Après avoir modifié mon code, je clique à nouveau sur "Do Javac".La façon la plus simple d'exécuter GuessVersion.class est de l'ouvrir dans JBindery, un autre outil du MRJ SDK 2.2. Le runtime est MRJ 2.2.6, une implémentation de Java 1.1.8.
la source
Je ne sais pas quel est mon score, car cela dépend de ce que vous considérez précisément comme un jeton lexical, mais j'essaie d'abuser autant que possible de ce système de comptage avec une longue chaîne ...
Cela dépend aussi si vous comptez cela comme identifiant 7 versions différentes ou 16 ... (Il pourrait être étendu jusqu'à 190).
Il fonctionne en tentant de définir une interface dans un chargeur de classe personnalisé avec des numéros de version principaux décroissants du format de classe. Le premier qui ne jette pas
java.lang.UnsupportedClassVersionError
correspond à la version de la VM.la source
String... args
.protected Class loadClass(String name, boolean resolve) { return Object.class; }
. Les documents API actuels négligent de mentionner en quoi il s'agissait d'une méthode abstraite avant Java 1.2. Je renvoie Object.class parce que la méthode reçoit un appel pour "java.lang.Object".L'algorithme d'internement a changé entre Java 6 et 7. Voir /programming//a/7224864/540552
XMLGregorianCalendar.equals (null) utilisé pour lancer NullPointerException dans java 5, mais cela a été corrigé dans java 6. Voir http://bugs.sun.com/view_bug.do?bug_id=6285370
10096928785 jetons ici. Merci à Peter Taylor d'avoir réduit 7 jetons.la source
DatatypeConfigurationException
cela ne sera pas lancé.int a
mais initialisez-le immédiatement, de sorte que leif
bloc devienne vide. Annulez la condition, supprimez le reste et utilisez--
au lieu de l'affectation directe àa
.