architecture du jeu d'instructions (ISA) de la machine virtuelle Java (JVM), le langage dans lequel Java et d'autres codes sources compatibles JVM sont compilés . Chaque instruction est représentée par un octet , d'où le nom de bytecode , ce qui en fait une forme compacte de données .
Grâce à la nature des machines virtuelles et du bytecode, un programme en bytecode JVM peut être exécuté sur n'importe quelle machine dotée d'une JVM compatible, sans le long processus de compilation à partir du code source.
Le bytecode JVM est utilisé lors de l'exécution , soit interprété par une JVM, soit compilé en code machine via la compilation juste-à-temps (JIT) et exécuté comme une application native.
Comme le bytecode JVM est conçu pour la compatibilité et la sécurité des logiciels multiplateformes , une application en bytecode JVM tend à fonctionner de manière cohérente sur différentes configurations matérielles et logicielles .
programmeur Java n'a pas besoin de comprendre le bytecode de la JVM ni même d'en avoir connaissance. Cependant, comme le suggère la revue IBM developerWorks, « comprendre le bytecode et celui qui est susceptible d'être généré par un compilateur Java aide le programmeur Java de la même manière que la connaissance de l'assembleur aide le programmeur C ou C++ ».Architecture du jeu d'instructions
Le bytecode comprend différents types d'instructions, notamment la manipulation de données, le transfert de contrôle, la création et la manipulation d'objets et l'appel de méthodes, qui font tous partie intégrante du modèle de programmation orienté objet de Java .
La JVM est à la fois une machine à pile et une machine à registres . Chaque cadre d'appel de méthode possède une « pile d'opérandes » et un tableau de « variables locales ». La pile d'opérandes sert à passer les opérandes aux calculs et à recevoir la valeur de retour d'une méthode appelée, tandis que les variables locales ont la même fonction que les registres et servent également à passer les arguments de la méthode. La taille maximale de la pile d'opérandes et du tableau de variables locales, calculée par le compilateur, fait partie des attributs de chaque méthode. Chacune peut être dimensionnée indépendamment de 0 à 65 535 valeurs, chaque valeur étant codée sur 32 bits. octet de code est composé d'un octet représentant le code opération , ainsi que de zéro ou plusieurs octets pour les opérandes.
Parmi les 256 codes d'opération possibles d'une longueur d'un octet , des préfixes et/ou des suffixes faisant référence aux types d'opérandes sur lesquels elles agissent. Les voici :
| Préfixe/suffixe | Type d'opérande |
|---|---|
i | entier |
l | long |
s | court |
b | octet |
c | personnage |
f | flotter |
d | double |
a | référence |
Par exemple, iaddadditionnera deux entiers, tandis daddqu'additionnera deux nombres à virgule flottante double précision. Les instructions const`&&`, `&&` loadet ` store&&` peuvent également prendre un suffixe de la forme ` n` , où n est un nombre compris entre 0 et 3 pour `&& ` et `&& `. La valeur maximale de n pour `&& ` varie selon le type._nloadstoreconst
Les constinstructions empilent une valeur du type spécifié. Par exemple, iconst_5empile un entier (valeur 32 bits) de valeur 5, tandis que dconst_1empile un nombre à virgule flottante double précision (valeur 64 bits) de valeur 1. Il existe également une instruction aconst_null`empile`, qui empile une thisistore_1
Exemple
Considérons le code Java suivant :
- Compilateur Eclipse pour Java (ECJ)
- Jikes , compile du Java en bytecode JVM (développé par IBM , implémenté en C++ ).
- Espresso compile du code Java en bytecode JVM (Java 1.0 uniquement).
- GNU Compiler for Java (GCJ) compile du Java en bytecode JVM ; il peut également compiler en code machine natif et faisait partie de la GNU Compiler Collection (GCC) jusqu'à la version 6.
Certains projets fournissent des assembleurs Java permettant d'écrire manuellement du bytecode JVM. Le code assembleur peut également être généré par la machine, par exemple par un compilateur ciblant une machine virtuelle Java. Parmi les assembleurs Java notables, on peut citer :
- langage d'assemblage de macros pour la machine virtuelle Java. La syntaxe Java est utilisée pour la définition des classes ou des interfaces. Les corps des méthodes sont spécifiés à l'aide d'instructions bytecode.
- Krakatau Bytecode Tools contient actuellement trois outils : un décompilateur et un désassembleur pour les fichiers de classe Java et un assembleur pour créer des fichiers de classe.
- Lilac, un assembleur et désassembleur pour la machine virtuelle Java.
D'autres ont développé des compilateurs, pour différents langages de programmation, afin de cibler la machine virtuelle Java, tels que :
- ColdFusion
- JRuby et Jython sont deux langages de script basés sur Ruby et Python.
- Apache Groovy est un langage généraliste optionnellement typé et dynamique, doté de fonctionnalités de typage statique et de compilation statique.
- Scala , un langage de programmation généraliste à typage statique prenant en charge la programmation orientée objet et fonctionnelle
- JGNAT et AppletMagic compilent le langage Ada en bytecode JVM
- Compilateurs de bytecode C vers Java
- Clojure est un langage fonctionnel, immuable et généraliste de la famille Lisp , fortement axé sur la concurrence.
- Kawa , une implémentation du langage Scheme , également un dialecte de Lisp
- MIDletPascal
- Le code JavaFX Script est compilé en bytecode JVM.
- Kotlin , un langage généraliste statiquement typé avec inférence de type
- Le code source Object Pascal est compilé en bytecode JVM à l'aide du compilateur Free Pascal 3.0+.
Exécution
Prise en charge des langues dynamiques
La spécification Java ( JSR ) 292 ( Prise en charge des langages à typage dynamique sur la plateforme Java ) a ajouté une nouvelle invokedynamicinstruction au niveau de la JVM, permettant l'appel de méthodes basé sur la vérification dynamique des types (au lieu de l'instruction existante à vérification statique invokevirtual). La machine Da Vinci est une implémentation prototype de machine virtuelle hébergeant des extensions JVM destinées à prendre en charge les langages dynamiques. Toutes les JVM compatibles avec Java Platform, Standard Edition (JSE) 7 incluent également cet invokedynamicopcode.