IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Tutoriel sur la compréhension de la machine virtuelle Java

Image non disponible

Tutoriel sur la comprhension de la machine virtuelle Java

Image non disponible


prcdentsommairesuivant

III-A. Getting Started

Pour commencer, nous allons voir un exemple complet d'une classe avec la mthode statique nomme add() de la partie prcdente qui additionne deux entiers.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
.class org/isk/jvmhardcore/bytecode/parttwo/Adder
 
  .method add(II)I
    iload_0
    iload_
    iadd
    ireturn
  .methodend
 
.classend

Source

Toutes les lignes commenant par un point (.) sont des directives et ce sont les choses qui nous intresseront dans cette partie.

Pour l'instant, nous nous limiterons au strict minimum nous permettant d'tudier nos premires instructions. Dans quelques semaines, nous recrerons cet assembleur extrmement simple. Nous pourrons ensuite y ajouter des fonctionnalits au fur et mesure.

La version quivalente en Java est la suivante:

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
package org.isk.jvmhardcore.bytecode.parttwo;
 
public class Adder {
  public static int add (int i1, int i2) {
    return i1 + i2;
  }
}

Pour tester la mthode add() de la version Plume, il nous faut tout d'abord assembler le fichier Adder.pjb en un fichier .class. partir de l, en ajoutant le fichier .class au classpath, nous pouvons appeler la mthode depuis un test unitaire crit en Java.

Pour assembler les fichiers .pjb en .class:

 
Sélectionnez
ant assemble

Le test unitaire correspondant est le suivant:

 
Sélectionnez
1.
2.
3.
4.
5.
6.
@Test
public void add0() {
  final int sum = Adder.add(2, 3);
 
  Assert.assertEquals(5, sum);
}

Source

Pour l'excuter depuis Ant:

 
Sélectionnez
ant test -DtestClass=org.isk.jvmhardcore.bytecode.parttwo.AdderTest -DtestMethod=add0

III-B. Descripteurs

Un descripteur est un moyen d'exprimer un type l'aide de lettres et de symboles:

  • la plupart des types sont reprsents par un seul caractre (I pour int, F pour float, ou de manire moins vidente Z pour boolean, J pour long, etc.);
  • le symbole [ indique un tableau du type indiqu ensuite. Par exemple [I signifie un tableau d'entiers. Il est possible d'avoir plusieurs crochets la suite pour indiquer des tableaux plusieurs dimensions ([[Z pour un tableau de tableaux de boolens);
  • la lettre L signifie un objet du type qui suit (Ljava/lang/String;);
  • seuls les types d'objets se terminent par un point virgule.

Tous les descripteurs possibles sont prsents dans le tableau suivant:

Descripteur

Type

Z

boolean

B

byte

S

short

C

char

I

int

J

long

F

float

D

double

V

void

[<type>

tableau de type <type>

L<type>;

Objet de type <type>

Note: tout comme en Java, en bytecode (et de fait dans un fichier .pjb), V (void) ne peut tre utilis qu'en type de retour d'une mthode.

Exemples:

Bytecode

Java

add(II)I

int add(int i1, int i2)

concat(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

String concat(String s1, String s2)

merge([Z[Z)[Z

boolean[] merge(boolean[] a1, boolean[] a2)

III-C. Commentaires

Les commentaires d'une seule ligne sont identifis soit par:

  • un signe dise (#);
  • un arobase (@);
  • un point virgule (;).

Tout ce qui ce trouve droite de ces signes est un commentaire.

Il est aussi possible d'avoir des commentaires de plusieurs lignes (/* … */):

 
Sélectionnez
1.
2.
3.
/* Ceci est
    un commentaire
    de plusieurs lignes */

III-D. Classes

La premire directive que nous allons voir est .class. Elle indique l'assembleur le nom compltement qualifi de la classe. De plus, ce nom indique le nom des rpertoires contenant le fichier et celui du fichier .class gnr.

 
Sélectionnez
1.
2.
3.
.class <nom compltement qualifi de la classe>
    # contenu de la classe
.endclass # Indique la fin d'une classe

Exemple:

 
Sélectionnez
1.
2.
3.
.class org/isk/jvmhardcore/bytecode/parttwo/Adder
    # ...
.endclass

quivalent Java:

 
Sélectionnez
1.
2.
3.
4.
5.
package org.isk.jvmhardcore.bytecode.parttwo;
 
public class Adder {
 
}

Le nom du package et de la classe sont concatns et les points inclus dans le nom du package sont remplacs par des slashes (/).

Le nom du package suivi de celui de la classe constituent le nom compltement qualifi d'une classe.

Limitations actuelles que nous lverons ultrieurement:

  • une seule directive .class par fichier est autorise;
  • une classe est obligatoirement publique (public).

III-E. Mthodes

Une mthode est dfinie de la manire suivante:

 
Sélectionnez
1.
2.
3.
.method <nom de la mthode>(<descripteur des paramtres>)<descripteur du retour>
   # Instructions
.endmethod

Notons que contrairement Java, le type de retour est compltement la fin, comme nous l'avons vu dans le tableau prcdent.

Notes:

  • pour indiquer plusieurs paramtres, il suffit de les crire les uns la suite des autres sans espace;
  • le descripteur de la mthode (paramtres et type de retour) doit tre unique. En revanche, contrairement Java, deux descripteurs peuvent diffrer uniquement par le type de retour.

Limitations actuelles:

  • une mthode est obligatoirement publique et statique (public static).

III-F. Noms

Les noms des packages, classes et mthodes doivent commencer par une lettre ASCII, le caractre underscore ‘_' ou dollar ‘$', puis des lettres ASCII, des chiffres ou les caractres underscore ‘_' ou dollar ‘$'.

Par exemple: helloworld, $hello_world1, _hello$world2, _my/$package/DoSomething1, etc.

III-G. Encodage

Le projet jvm_hardcore doit tre en UTF-8.

III-H. Crer un fichier classe en Java

PJBA permet de crer un fichier .class partir d'un fichier texte comme nous venons de le voir. Mais il est aussi possible d'utiliser des objets Java. Nanmoins en l'tat, pour qui ne sait pas de quoi est constitu le format .class, son utilisation est plutt complique.

En reprenant encore une fois notre exemple de mthode add():

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
@Test
public void assembleJava() throws Exception {
  // ConstantPoolEntries
  final String className = "org/isk/jvmhardcore/bytecode/parttwo/AdderJava";
  final String methodName = "add";
  final String methodDescriptor = "(II)I";
 
  // ClassFile
  final ClassFile classFile = new ClassFile(className);
  final int classNameIndex = classFile.addConstantUTF8(className);
  final int thisClassIndex = classFile.addConstantClass(classNameIndex);
  classFile.setThisClassIndex(thisClassIndex);
 
  // Method
  final int codeAttributeIndex = classFile.addConstantUTF8(Code.ATTRIBUTE_NAME);
  final int methodIndex = classFile.addConstantUTF8(methodName);
  final int descriptorIndex = classFile.addConstantUTF8(methodDescriptor);
  final Method method = new Method(codeAttributeIndex);
  method.setNameIndex(methodIndex);
  final int parameterCount = Method.getParameterCount(methodDescriptor);
  method.setDescriptorIndex(descriptorIndex, parameterCount);
  classFile.addMethod(method);
 
  // Instructions
  method.addInstruction(Instructions.iload_0());
  method.addInstruction(Instructions.iload_1());
  method.addInstruction(Instructions.iadd());
  method.addInstruction(Instructions.ireturn());
 
  this.createFile(classFile);
}

Source

Je ne m'attarderai pas sur cet exemple, nous y reviendrons un peu plus tard. De plus, une de nos actions sera de simplifier l'utilisation de PJBA en mode Java puisque mme si l'on sait quoi tout ceci correspond, 30 lignes pour crer une classe et une mthode qui ne fait qu'une addition, cela fait beaucoup.

Pour tester cette classe:

 
Sélectionnez
ant assemble
ant test -DtestClass=org.isk.jvmhardcore.bytecode.parttwo.AdderTest -DtestMethod=add1

Source du test

III-I. Utilisation du code source

Pour pouvoir assembler les fichiers .pjb en .class, la structure des projets a d voluer:

 
Sélectionnez
project
|  +- 01_src (code source)
|  |  +- main
|  |  |  +- assembler (Assembleur)
|  |  |  +- java
|  |  |  +- pjb (Plume Java Bytecode)
|  |  +- test
|  |  |  +- java
|  |  |  +- resources
|  +- 02_build (gnr)
|  |  |  +- assembler
|  |  |  |  +- classes (Assembleur compil)
|  |  |  |  +- reports (Rapport d'assemblage)
|  |  |  +- classes
|  |  |  +- junit-data
|  |  |  +- junit-reports
|  |  |  +- pjb-classes (.pjb assembls en .class)
|  |  |  +- test-classes
|  +- 03_dist (gnr)

III-I-1. Assembleur

Le rpertoire 01_src/main/assembler/ contient les classes permettant de gnrer des fichiers .class partir d'un fichier .pjb ou du code Java. Par simplicit, le choix a t fait d'utiliser JUnit au lieu d'une mthode main() pour excuter l'assembleur.

Le rpertoire 02_build/assembler/ contient les composants compils de l'assembleur et les rapports des tests unitaires excuts pour pouvoir gnrer des fichiers .class.

La mthode assemblePjb() prend tous les fichiers du rpertoire pjb/ et de ses enfants quelle que soit leur extension et appelle le parser PJBA (disponible dans le rpertoire 02_libs sous le nom pjba.jar).

Les fichiers gnrs sont crs dans le rpertoire 02_build/pjb-classes. Il doit tre par consquent rajout au classpath pour que les tests unitaires testant ces classes et mthodes puissent y accder.

III-I-2. Scripts de construction Ant

Une target assemble - dj prsente au cours de cet article - a t rajoute.

 
Sélectionnez
ant assemble

De plus, pour que les scripts de construction restent simples et qu'il soit possible de compiler/assembler tous les projets partir du script principal (celui la racine du projet), toutes les commandes (targets) Ant sont accessibles depuis le rpertoire root de n'importe quel projet. Par consquent, il est possible d'utiliser la target compile sur le projet bytecode/ alors que le rpertoire 01_src/main/java n'existe pas. Son excution se terminera en succs, mais ne fera rien, puisque nous testons si le rpertoire 01_src/main/java existe avant de poursuivre l'excution.

III-J. What's next ?

Au cours de cet article, nous nous sommes content de reprsenter une classe sous une forme proche de sa reprsentation en bytecode. Les choses srieuses commenceront ds l'article suivant. Nous tudierons nos premires instructions.


prcdentsommairesuivant

Copyright © 2016 SOAT. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.