Comment savoir la version de la JVM d’un .class ?

LiB et Java

Compatibilité ascendante et descendante

L’un des avantages de Java lorsqu’on doit entretenir un parc applicatif étendu c’est la compatibilité ascendante de la machine virtuelle Java.

En effet, à quelques exceptions près, un code Java compilé en 1999 avec le JDK 1.1 marche aujourd’hui lorsqu’on l’exécute avec une JVM 1.6. Par contre, l’inverse n’est pas vrai, la machine virtuelle Java n’assure pas une compatibilité descendante, i.e. une classe compilée pour la JVM 1.6 ne s’exécuterait pas sur une JVM 1.5.

Normalement cela n’est pas un problème… sauf quand on doit impérativement exécuter un code dans une ancienne version de la machine virtuelle. Dans ce cas là, on a intérêt à s’assurer que le code a été compilé pour cette JVM (ou pour une JVM plus ancienne) avant d’essayer de l’exécuter.

Comment peut-on donc savoir la version de la JVM utilisée comme cible de la compilation une classe Java ?

Pour garantir que les applications Java puissent d’exécuter à l’identique sur les différents plateformes, les fichiers .class ont un format figé. De cette façon, lorsqu’on compile du Java sur n’importe quel plateforme, on obtient les mêmes fichiers .class.

Les fichiers .class ont donc une structure fixe, ils sont découpés en dix sections (certaines à taille variable), et c’est dans la deuxième section qu’on va trouver la réponse à notre question.

La première section, c’est le magic_number. Ce paramètre, codé sur 4 octets, permet à la JVM de reconnaître le fichier comme une classe Java. Le valeur de ce magic_number est 0xCA 0xFE 0xBA 0xBE (CAFEBABE).

Les 4 octets suivantes définissent la version de la JVM utilisée comme cible de la compilation. Les deux premiers octets sont la version mineure (normalement 0) et les deux suivants indiquent la version majeure. C’est cette version majeure qui donne donc la réponse à notre question :

J2SE 6.0 = 50 (0x32 hex),
J2SE 5.0 = 49 (0x31 hex),
JDK 1.4 = 48 (0x30 hex),
JDK 1.3 = 47 (0x2F hex),
JDK 1.2 = 46 (0x2E hex),
JDK 1.1 = 45 (0x2D hex).

Pour voir donc la version de la JVM utilisée comme cible lors de la compilation d’une classe, il suffit d’ouvrir la classe avec un éditeur hexadécimal (moi j’utilise la commande hexdump -C) et regarder le début du fichier, qui sera de la forme CA FE BA BE 00 00 00 XXXX indique la version.

Par exemple, pour une classe compilée pour JVM 1.5 on aurait CA FE BA BE 00 00 00 31

Merci à Mathias de m’avoir mis sur la piste. Ce soir je me coucherai moins bête…

Tags:

4 commentaires à “Comment savoir la version de la JVM d’un .class ?”

  1. adiGuba Says:

    Salut,

    Sous les systèmes Linux il suffit d’utiliser l’application “file” :

    file MyClass.class

    Qui donne une réponse du style :

    MyClass.class: compiled Java class data, version 49.0

    a++

  2. LostInBrittany Says:

    En effet, ça marche !

    Il suffit donc utiliser la petite table de conversion pour savoir que 49 correspond à la JVM 1.5 et le tour est joué, plus simple que avec hexdump.

    Merci ! :)

  3. Raf177 Says:

    J’ai une version qui fonctionne quelque soit l’OS, car livré en même temps que java : javap -verbose MyClass

  4. LostInBrittany Says:

    C’est marrant, après une dizaine d’années à travailler sur Java, j’ignorais cette utilisation de la commande javap :D

    Bonne méthode pour les fichiers .class, quoi quelle ne marche pas pour les .jar (là où le dump hexadécimal continue à marcher).

Leave a Reply