bytecode Java - Java bytecode

Le bytecode Java est le jeu d'instructions de la machine virtuelle Java (JVM).

Relation avec Java

Un programmeur Java n'a pas du tout besoin de connaître ou de comprendre le bytecode Java. Cependant, comme suggéré dans le journal IBM developerWorks, "Comprendre le bytecode et quel bytecode 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' assembly aide le programmeur C ou C++ ."

Architecture d'ensemble d'instructions

La JVM est à la fois une machine à pile et une machine à registre . Chaque trame pour un appel de méthode a une "pile d'opérandes" et un tableau de "variables locales". La pile d'opérandes est utilisée pour les opérandes des calculs et pour recevoir la valeur de retour d'une méthode appelée, tandis que les variables locales ont le même objectif que les registres et sont également utilisées pour transmettre des arguments de 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. Chacun peut être dimensionné indépendamment de 0 à 65535 valeurs, où chaque valeur est de 32 bits. longet les doubletypes, qui sont de 64 bits, occupent deux variables locales consécutives (qui n'ont pas besoin d'être alignées sur 64 bits dans le tableau de variables locales) ou une valeur dans la pile d'opérandes (mais sont comptées comme deux unités dans la profondeur de la pile) .

Jeu d'instructions

Chaque bytecode est composé d'un octet qui représente l' opcode , avec zéro ou plusieurs octets pour les opérandes.

Sur les 256 opcodes possibles de long octet , en 2015, 202 sont en cours d'utilisation (~79%), 51 sont réservés pour une utilisation future (~20%), et 3 instructions (~1%) sont réservées en permanence aux implémentations JVM pour utilisation. Deux d'entre eux ( impdep1et impdep2) doivent fournir des pièges pour le logiciel et le matériel spécifiques à l'implémentation, respectivement. Le troisième est utilisé par les débogueurs pour implémenter des points d'arrêt.

Les instructions se répartissent en plusieurs grands groupes :

  • Charger et stocker (par exemple aload_0, istore)
  • Arithmétique et logique (par exemple ladd, fcmpl)
  • Conversion de type (par exemple i2b, d2i)
  • Création et manipulation d'objets ( new, putfield)
  • Gestion de la pile d'opérandes (par exemple swap, dup2)
  • Transfert de contrôle (par exemple ifeq, goto)
  • Invocation et retour de méthode (par exemple invokespecial, areturn)

Il existe également quelques instructions pour un certain nombre de tâches plus spécialisées telles que le lancement d'exceptions, la synchronisation, etc.

De nombreuses instructions ont des préfixes et/ou des suffixes faisant référence aux types d'opérandes sur lesquels elles opèrent. Ceux-ci sont les suivants :

Préfixe suffixe Type d'opérande
i entier
l longue
s court
b octet
c personnage
f flotter
d double
a référence

Par exemple, iaddajoutera deux nombres entiers, tandis que daddajoutera deux doubles. Les instructions const, load, et storepeuvent également prendre un suffixe de la forme , où n est un nombre compris entre 0 et 3 pour et . Le n maximum pour diffère selon le type. _nloadstoreconst

Les constinstructions poussent une valeur du type spécifié sur la pile. Par exemple, iconst_5poussera un entier (valeur 32 bits) avec la valeur 5 sur la pile, tandis que dconst_1poussera un double (valeur à virgule flottante 64 bits) avec la valeur 1 sur la pile. Il y a aussi un aconst_null, qui pousse une nullréférence. Le n pour les instructions loadet storespécifie l'index dans le tableau de variables locales à partir duquel charger ou stocker. L' aload_0instruction pousse l'objet dans la variable locale 0 sur la pile (c'est généralement l' thisobjet). istore_1stocke l'entier en haut de la pile dans la variable locale 1. Pour les variables locales au-delà de 3, le suffixe est supprimé et les opérandes doivent être utilisés.

Exemple

Considérez le code Java suivant :

outer:
for (int i = 2; i < 1000; i++) {
    for (int j = 2; j < i; j++) {
        if (i % j == 0)
            continue outer;
    }
    System.out.println (i);
}

Un compilateur Java peut traduire le code Java ci-dessus en bytecode comme suit, en supposant que ce qui précède a été mis dans une méthode :

0:   iconst_2
1:   istore_1
2:   iload_1
3:   sipush  1000
6:   if_icmpge       44
9:   iconst_2
10:  istore_2
11:  iload_2
12:  iload_1
13:  if_icmpge       31
16:  iload_1
17:  iload_2
18:  irem
19:  ifne    25
22:  goto    38
25:  iinc    2, 1
28:  goto    11
31:  getstatic       #84; // Field java/lang/System.out:Ljava/io/PrintStream;
34:  iload_1
35:  invokevirtual   #85; // Method java/io/PrintStream.println:(I)V
38:  iinc    1, 1
41:  goto    2
44:  return

Génération

Le langage le plus courant ciblant la machine virtuelle Java en produisant du bytecode Java est Java. A l'origine, un seul compilateur existait, le compilateur javac de Sun Microsystems , qui compile le code source Java en bytecode Java ; mais parce que toutes les spécifications pour le bytecode Java sont maintenant disponibles, d'autres parties ont fourni des compilateurs qui produisent du bytecode Java. Voici des exemples d'autres compilateurs :

  • Compilateur Eclipse pour Java (ECJ)
  • Jikes , compile de Java en bytecode Java (développé par IBM , implémenté en C++ )
  • Espresso, compile de Java en bytecode Java (Java 1.0 uniquement)
  • Compilateur GNU pour Java (GCJ), compile de Java en bytecode Java ; 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 pour permettre l'écriture de bytecode Java à la main. Le code assembleur peut également être généré par machine, par exemple par un compilateur ciblant une machine virtuelle Java . Les assembleurs Java notables incluent :

  • Jasmin , prend des descriptions de texte pour les classes Java, écrites dans une syntaxe simple de type assemblage à l'aide du jeu d'instructions de la machine virtuelle Java et génère un fichier de classe Java
  • Jamaica, un langage d'assemblage de macros pour la machine virtuelle Java . La syntaxe Java est utilisée pour la définition de classe ou d'interface. Les corps de méthode sont spécifiés à l'aide d'instructions de 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, pour cibler la machine virtuelle Java, tels que :

Exécution

Il existe plusieurs machines virtuelles Java disponibles aujourd'hui pour exécuter le bytecode Java, à la fois des produits gratuits et commerciaux. Si l'exécution du bytecode dans une machine virtuelle n'est pas souhaitable, un développeur peut également compiler le code source Java ou le bytecode directement en code machine natif avec des outils tels que le compilateur GNU pour Java (GCJ). Certains processeurs peuvent exécuter nativement le bytecode Java. De tels processeurs sont appelés processeurs Java .

Prise en charge des langues dynamiques

La machine virtuelle Java fournit une certaine prise en charge des langages à typage dynamique . La plupart du jeu d'instructions JVM existant est typé statiquement - dans le sens où les appels de méthode ont leurs signatures vérifiées au moment de la compilation , sans mécanisme pour reporter cette décision à l' exécution , ou pour choisir l'envoi de la méthode par une approche alternative.

JSR 292 ( Prise en charge des langages de type dynamique sur la plate-forme Java ) a ajouté une nouvelle invokedynamicinstruction au niveau de la JVM, pour permettre l'invocation de méthode reposant sur la vérification de type dynamique (au lieu de l' invokevirtualinstruction à vérification de type statique existante ). La machine Da Vinci est un prototype d'implémentation de machine virtuelle qui héberge des extensions JVM visant à prendre en charge les langages dynamiques. Toutes les JVM prenant en charge JSE 7 incluent également l' invokedynamicopcode.

Voir également

Les références

Liens externes